Dynamic动态Json解析帮助类,C#动态解析JSON方法,

不用model直接解析JSON,方便快捷的首选方式,

Dynamic动态解析JSON代码量最起码减少一半


DynJsonHelper 全称为DynamicJsonHelper
中文简称:动态Json解析帮助类
开始封装时间:2016.3.30(持续更新中)
适用版本:.NET Framework 4.0以上版本(包含.NET4.0)
核心技术:运用Dynamic特性将json字符串自动转换为Dynamic Object实现动态解析json数组
核心理念:采用动态解析json数据的方式,去除.Net中对Model实体对象封装,
               达到节约时间成本、精简代码、提高开发效率的目的
调用方法:暂时封装了两个实用方法
               Json字符串转为Json对象 : DynJsonHelper.ToObject(Json字符串);
               数组/对象转为Json字符串:DynJsonHelper.ToJson(数组/对象);


DynJsonHelper源码下载

001using System;
002using System.Collections;
003using System.Collections.Generic;
004using System.Diagnostics;
005using System.Dynamic;
006using System.IO;
007using System.Linq;
008using System.Reflection;
009using System.Runtime.Serialization.Json;
010using System.Text;
011using System.Xml;
012using System.Xml.Linq;
013 
014namespace AutoHome.JsonDynamic
015{
016    /**
017     * DynJsonHelper 全称为DynamicJsonHelper
018     * 中文简称:动态Json解析帮助类
019     * 开始封装时间:2016.3.30(持续更新中)
020     * 适用版本:.NET Framework 4.0以上版本(包含.NET4.0)
021     * 核心技术:运用Dynamic特性将json字符串自动转换为Dynamic Object实现动态解析json数组
022     * 核心理念:采用动态解析json数据的方式,去除.Net中对Model实体对象封装,
023     *          达到节约时间成本、精简代码、提高开发效率的目的
024     * 调用方法:暂时封装了两个实用方法
025     *          Json字符串转为Json对象 : DynJsonHelper.ToObject(Json字符串);
026     *          数组/对象转为Json字符串:DynJsonHelper.ToJson(数组/对象);
027     *
028     *
029     * **/
030    public class DynJsonHelper : DynamicObject
031    {
032 
033        #region Json操作方法
034        /// <summary>
035        /// 把Json字符串转为Json对象
036        /// </summary>
037        /// <param name="json">String类型 符合Json规范的字符串</param>
038        /// <returns>Json对象或Json数组List</returns>
039        public static dynamic ToObject(string json)
040        {
041            return ToObject(json, Encoding.Unicode);
042        }
043        /// <summary>
044        /// 把Json字符串转为Json对象(可自定义编码)
045        /// </summary>
046        /// <param name="json">String类型 符合Json规范的字符串</param>
047        ///  <param name="encoding">自定义编码</param>
048        /// <returns>Json对象或Json数组List</returns>
049        public static dynamic ToObject(string json, Encoding encoding)
050        {
051            try
052            {
053                using (var reader = JsonReaderWriterFactory.CreateJsonReader(encoding.GetBytes(json), XmlDictionaryReaderQuotas.Max))
054                {
055                    return ToValue(XElement.Load(reader));
056                }
057            }
058            catch (Exception exc) { return exc.Message; }
059        }
060        /// <summary>
061        /// 把Stream类型的Json数据转为Json对象
062        /// </summary>
063        /// <param name="stream">Stream类型Json数据</param>
064        /// <returns>Json对象或Json数组List</returns>
065        public static dynamic ToObject(Stream stream)
066        {
067            try
068            {
069                using (var reader = JsonReaderWriterFactory.CreateJsonReader(stream, XmlDictionaryReaderQuotas.Max))
070                {
071                    return ToValue(XElement.Load(reader));
072                }
073            }
074            catch (Exception exc) { return exc.Message; }
075        }
076        /// <summary>
077        /// 把Stream类型的Json数据转为Json对象
078        /// </summary>
079        /// <param name="stream">Stream类型Json数据</param>
080        /// <param name="encoding">自定义编码</param>
081        /// <returns>Json对象或Json数组List</returns>
082        public static dynamic ToObject(Stream stream, Encoding encoding)
083        {
084            try
085            {
086                using (var reader = JsonReaderWriterFactory.CreateJsonReader(stream, encoding, XmlDictionaryReaderQuotas.Max, _ => { }))
087                {
088                    return ToValue(XElement.Load(reader));
089                }
090            }
091            catch (Exception exc) { return exc.Message; }
092        }
093        /// <summary>
094        /// 把对象或者List数组转为Json字符串(支持复杂对象转换)
095        /// </summary>
096        /// <param name="obj">object</param>
097        /// <returns>Json字符串</returns>
098        public static string ToJson(object obj)
099        {
100            return CreateJsonString(new XStreamingElement("root", CreateTypeAttr(GetJsonType(obj)), CreateJsonNode(obj)));
101        }
102        #endregion
103 
104        #region 私有方法
105        /// <summary>
106        /// 枚举定义Json类型
107        /// </summary>
108        private enum JsonType
109        {
110            @string, number, boolean, @object, array, @null
111        }
112        /// <summary>
113        /// 处理不同类型的Value
114        /// </summary>
115        /// <param name="element"></param>
116        /// <returns></returns>
117        private static dynamic ToValue(XElement element)
118        {
119            var type = (JsonType)Enum.Parse(typeof(JsonType), element.Attribute("type").Value);
120            switch (type)
121            {
122                case JsonType.boolean:
123                    return (bool)element;
124                case JsonType.number:
125                    return (double)element;
126                case JsonType.@string:
127                    return (string)element;
128                case JsonType.@object:
129                case JsonType.array:
130                    return new DynJsonHelper(element, type);
131                case JsonType.@null:
132                default:
133                    return null;
134            }
135        }
136        /// <summary>
137        /// 获取Json字段类型
138        /// </summary>
139        /// <param name="obj"></param>
140        /// <returns></returns>
141        private static JsonType GetJsonType(object obj)
142        {
143            if (obj == null) return JsonType.@null;
144 
145            switch (Type.GetTypeCode(obj.GetType()))
146            {
147                case TypeCode.Boolean:
148                    return JsonType.boolean;
149                case TypeCode.String:
150                case TypeCode.Char:
151                case TypeCode.DateTime:
152                    return JsonType.@string;
153                case TypeCode.Int16:
154                case TypeCode.Int32:
155                case TypeCode.Int64:
156                case TypeCode.UInt16:
157                case TypeCode.UInt32:
158                case TypeCode.UInt64:
159                case TypeCode.Single:
160                case TypeCode.Double:
161                case TypeCode.Decimal:
162                case TypeCode.SByte:
163                case TypeCode.Byte:
164                    return JsonType.number;
165                case TypeCode.Object:
166                    return (obj is IEnumerable) ? JsonType.array : JsonType.@object;
167                case TypeCode.DBNull:
168                case TypeCode.Empty:
169                default:
170                    return JsonType.@null;
171            }
172        }
173 
174        private static XAttribute CreateTypeAttr(JsonType type)
175        {
176            return new XAttribute("type", type.ToString());
177        }
178 
179        private static object CreateJsonNode(object obj)
180        {
181            var type = GetJsonType(obj);
182            switch (type)
183            {
184                case JsonType.@string:
185                case JsonType.number:
186                    return obj;
187                case JsonType.boolean:
188                    return obj.ToString().ToLower();
189                case JsonType.@object:
190                    return CreateXObject(obj);
191                case JsonType.array:
192                    return CreateXArray(obj as IEnumerable);
193                case JsonType.@null:
194                default:
195                    return null;
196            }
197        }
198        private static IEnumerable<XStreamingElement> CreateXArray<T>(T obj) where T : IEnumerable
199        {
200            return obj.Cast<object>()
201                .Select(o => new XStreamingElement("item", CreateTypeAttr(GetJsonType(o)), CreateJsonNode(o)));
202        }
203        private static IEnumerable<XStreamingElement> CreateXObject(object obj)
204        {
205            return obj.GetType()
206                .GetProperties(BindingFlags.Public | BindingFlags.Instance)
207                .Select(pi => new { Name = pi.Name, Value = pi.GetValue(obj, null) })
208                .Select(a => new XStreamingElement(a.Name, CreateTypeAttr(GetJsonType(a.Value)), CreateJsonNode(a.Value)));
209        }
210        private static string CreateJsonString(XStreamingElement element)
211        {
212            try
213            {
214                using (var ms = new MemoryStream())
215                using (var writer = JsonReaderWriterFactory.CreateJsonWriter(ms, Encoding.Unicode))
216                {
217                    element.WriteTo(writer);
218                    writer.Flush();
219                    return Encoding.Unicode.GetString(ms.ToArray());
220                }
221            }
222            catch (Exception exc) { return exc.Message; }
223        }
224        //动态处理对象和数组List
225        readonly XElement xml;
226        readonly JsonType jsonType;
227        /// <summary>
228        /// 创建无参构造函数
229        /// </summary>
230        public DynJsonHelper()
231        {
232            xml = new XElement("root", CreateTypeAttr(JsonType.@object));
233            jsonType = JsonType.@object;
234        }
235        private DynJsonHelper(XElement element, JsonType type)
236        {
237            Debug.Assert(type == JsonType.array || type == JsonType.@object);
238            xml = element;
239            jsonType = type;
240        }
241        public bool IsObject { get { return jsonType == JsonType.@object; } }
242        public bool IsArray { get { return jsonType == JsonType.array; } }
243        /// <summary>
244        /// 类型属性验证
245        /// </summary>
246        /// <param name="name"></param>
247        /// <returns></returns>
248        public bool IsDefined(string name)
249        {
250            return IsObject && (xml.Element(name) != null);
251        }
252        /// <summary>
253        /// 类型属性验证
254        /// </summary>
255        /// <param name="index"></param>
256        /// <returns></returns>
257        public bool IsDefined(int index)
258        {
259            return IsArray && (xml.Elements().ElementAtOrDefault(index) != null);
260        }
261 
262        /// <summary>
263        /// 删除属性
264        /// </summary>
265        /// <param name="name"></param>
266        /// <returns></returns>
267        public bool Delete(string name)
268        {
269            var elem = xml.Element(name);
270            if (elem != null)
271            {
272                elem.Remove();
273                return true;
274            }
275            else return false;
276        }
277 
278        /// <summary>
279        /// 删除属性
280        /// </summary>
281        /// <param name="index"></param>
282        /// <returns></returns>
283        public bool Delete(int index)
284        {
285            var elem = xml.Elements().ElementAtOrDefault(index);
286            if (elem != null)
287            {
288                elem.Remove();
289                return true;
290            }
291            else return false;
292        }
293        /// <summary>
294        /// 映射到数组或类的公共属性名
295        /// </summary>
296        /// <typeparam name="T"></typeparam>
297        /// <returns></returns>
298        public T Deserialize<T>()
299        {
300            return (T)Deserialize(typeof(T));
301        }
302        private object Deserialize(Type type)
303        {
304            return (IsArray) ? DeserializeArray(type) : DeserializeObject(type);
305        }
306        private dynamic DeserializeValue(XElement element, Type elementType)
307        {
308            var value = ToValue(element);
309            if (value is DynJsonHelper)
310            {
311                value = ((DynJsonHelper)value).Deserialize(elementType);
312            }
313            return Convert.ChangeType(value, elementType);
314        }
315        private object DeserializeObject(Type targetType)
316        {
317            var result = Activator.CreateInstance(targetType);
318            var dict = targetType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
319                .Where(p => p.CanWrite)
320                .ToDictionary(pi => pi.Name, pi => pi);
321            foreach (var item in xml.Elements())
322            {
323                PropertyInfo propertyInfo;
324                if (!dict.TryGetValue(item.Name.LocalName, out propertyInfo)) continue;
325                var value = DeserializeValue(item, propertyInfo.PropertyType);
326                propertyInfo.SetValue(result, value, null);
327            }
328            return result;
329        }
330        private object DeserializeArray(Type targetType)
331        {
332            if (targetType.IsArray) // Jsons[]==>数组[]
333            {
334                var elemType = targetType.GetElementType();
335                dynamic array = Array.CreateInstance(elemType, xml.Elements().Count());
336                var index = 0;
337                foreach (var item in xml.Elements())
338                {
339                    array[index  ] = DeserializeValue(item, elemType);
340                }
341                return array;
342            }
343            else // Jsons<Foo>==>List
344            {
345                var elemType = targetType.GetGenericArguments()[0];
346                dynamic list = Activator.CreateInstance(targetType);
347                foreach (var item in xml.Elements())
348                {
349                    list.Add(DeserializeValue(item, elemType));
350                }
351                return list;
352            }
353        }
354        /// <summary>
355        /// 删除
356        /// </summary>
357        /// <param name="binder"></param>
358        /// <param name="args"></param>
359        /// <param name="result"></param>
360        /// <returns></returns>
361        public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
362        {
363            result = (IsArray)
364                ? Delete((int)args[0])
365                : Delete((string)args[0]);
366            return true;
367        }
368        /// <summary>
369        /// 重写TryInvokeMember方法
370        /// </summary>
371        /// <param name="binder"></param>
372        /// <param name="args"></param>
373        /// <param name="result"></param>
374        /// <returns></returns>
375        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
376        {
377            if (args.Length > 0)
378            {
379                result = null;
380                return false;
381            }
382            result = IsDefined(binder.Name);
383            return true;
384        }
385        /// <summary>
386        /// 重写TryConvert方法
387        /// Deserialize or foreach(IEnumerable)
388        /// </summary>
389        /// <param name="binder"></param>
390        /// <param name="result"></param>
391        /// <returns></returns>
392        public override bool TryConvert(ConvertBinder binder, out object result)
393        {
394            if (binder.Type == typeof(IEnumerable) || binder.Type == typeof(object[]))
395            {
396                var ie = (IsArray)
397                    ? xml.Elements().Select(x => ToValue(x))
398                    : xml.Elements().Select(x => (dynamic)new KeyValuePair<string, object>(x.Name.LocalName, ToValue(x)));
399                result = (binder.Type == typeof(object[])) ? ie.ToArray() : ie;
400            }
401            else
402            {
403                result = Deserialize(binder.Type);
404            }
405            return true;
406        }
407        private bool TryGet(XElement element, out object result)
408        {
409            if (element == null)
410            {
411                result = null;
412                return false;
413            }
414 
415            result = ToValue(element);
416            return true;
417        }
418        public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
419        {
420            return (IsArray)
421                ? TryGet(xml.Elements().ElementAtOrDefault((int)indexes[0]), out result)
422                : TryGet(xml.Element((string)indexes[0]), out result);
423        }
424        public override bool TryGetMember(GetMemberBinder binder, out object result)
425        {
426            return (IsArray)
427                ? TryGet(xml.Elements().ElementAtOrDefault(int.Parse(binder.Name)), out result)
428                : TryGet(xml.Element(binder.Name), out result);
429        }
430        private bool TrySet(string name, object value)
431        {
432            var type = GetJsonType(value);
433            var element = xml.Element(name);
434            if (element == null)
435            {
436                xml.Add(new XElement(name, CreateTypeAttr(type), CreateJsonNode(value)));
437            }
438            else
439            {
440                element.Attribute("type").Value = type.ToString();
441                element.ReplaceNodes(CreateJsonNode(value));
442            }
443 
444            return true;
445        }
446        private bool TrySet(int index, object value)
447        {
448            var type = GetJsonType(value);
449            var e = xml.Elements().ElementAtOrDefault(index);
450            if (e == null)
451            {
452                xml.Add(new XElement("item", CreateTypeAttr(type), CreateJsonNode(value)));
453            }
454            else
455            {
456                e.Attribute("type").Value = type.ToString();
457                e.ReplaceNodes(CreateJsonNode(value));
458            }
459 
460            return true;
461        }
462        public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
463        {
464            return (IsArray)
465                ? TrySet((int)indexes[0], value)
466                : TrySet((string)indexes[0], value);
467        }
468        public override bool TrySetMember(SetMemberBinder binder, object value)
469        {
470            return (IsArray)
471                ? TrySet(int.Parse(binder.Name), value)
472                : TrySet(binder.Name, value);
473        }
474        public override IEnumerable<string> GetDynamicMemberNames()
475        {
476            return (IsArray)
477                ? xml.Elements().Select((x, i) => i.ToString())
478                : xml.Elements().Select(x => x.Name.LocalName);
479        }
480        /// <summary>
481        /// 重写ToString方法
482        /// </summary>
483        /// <returns></returns>
484        public override string ToString()
485        {
486            //无法序列化就剔除
487            foreach (var elem in xml.Descendants().Where(x => x.Attribute("type").Value == "null"))
488            {
489                elem.RemoveNodes();
490            }
491            return CreateJsonString(new XStreamingElement("root", CreateTypeAttr(jsonType), xml.Elements()));
492        }
493        #endregion
494 
495    }
496}


原文链接:Dynamic动态Json解析帮助类