• Using C# 4.0 and dynamic to parse JSON


    An alternative deserialisation approach is suggested here. I modified the code slightly to fix a bug and suit my coding style. All you need is this:

    View Code
      1 using System;
      2 using System.Collections;
      3 using System.Collections.Generic;
      4 using System.Collections.ObjectModel;
      5 using System.Dynamic;
      6 using System.Linq;
      7 using System.Text;
      8 using System.Web.Script.Serialization;
      9 
     10 private sealed class DynamicJsonConverter : JavaScriptConverter
     11 {
     12     public override object Deserialize(IDictionary<stringobject> dictionary, Type type, JavaScriptSerializer serializer)
     13     {
     14         if (dictionary == null)
     15             throw new ArgumentNullException("dictionary");
     16 
     17         return type == typeof(object) ? new DynamicJsonObject(dictionary) : null;
     18     }
     19 
     20     public override IDictionary<stringobject> Serialize(object obj, JavaScriptSerializer serializer)
     21     {
     22         throw new NotImplementedException();
     23     }
     24 
     25     public override IEnumerable<Type> SupportedTypes
     26     {
     27         get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(object) })); }
     28     }
     29 
     30     #region Nested type: DynamicJsonObject
     31 
     32     private sealed class DynamicJsonObject : DynamicObject
     33     {
     34         private readonly IDictionary<stringobject> _dictionary;
     35 
     36         public DynamicJsonObject(IDictionary<stringobject> dictionary)
     37         {
     38             if (dictionary == null)
     39                 throw new ArgumentNullException("dictionary");
     40             _dictionary = dictionary;
     41         }
     42 
     43         public override string ToString()
     44         {
     45             var sb = new StringBuilder("{");
     46             ToString(sb);
     47             return sb.ToString();
     48         }
     49 
     50         private void ToString(StringBuilder sb)
     51         {
     52             var firstInDictionary = true;
     53             foreach (var pair in _dictionary)
     54             {
     55                 if (!firstInDictionary)
     56                     sb.Append(",");
     57                 firstInDictionary = false;
     58                 var value = pair.Value;
     59                 var name = pair.Key;
     60                 if (value is string)
     61                 {
     62                     sb.AppendFormat("{0}:\"{1}\"", name, value);
     63                 }
     64                 else if (value is IDictionary<stringobject>)
     65                 {
     66                     new DynamicJsonObject((IDictionary<stringobject>)value).ToString(sb);
     67                 }
     68                 else if (value is ArrayList)
     69                 {
     70                     sb.Append(name + ":[");
     71                     var firstInArray = true;
     72                     foreach (var arrayValue in (ArrayList)value)
     73                     {
     74                         if (!firstInArray)
     75                             sb.Append(",");
     76                         firstInArray = false;
     77                         if (arrayValue is IDictionary<stringobject>)
     78                             new DynamicJsonObject((IDictionary<stringobject>)arrayValue).ToString(sb);
     79                         else if (arrayValue is string)
     80                             sb.AppendFormat("\"{0}\"", arrayValue);
     81                         else
     82                             sb.AppendFormat("{0}", arrayValue);
     83 
     84                     }
     85                     sb.Append("]");
     86                 }
     87                 else
     88                 {
     89                     sb.AppendFormat("{0}:{1}", name, value);
     90                 }
     91             }
     92             sb.Append("}");
     93         }
     94 
     95         public override bool TryGetMember(GetMemberBinder binder, out object result)
     96         {
     97             if (!_dictionary.TryGetValue(binder.Name, out result))
     98             {
     99                 // return null to avoid exception.  caller can check for null this way...
    100                 result = null;
    101                 return true;
    102             }
    103 
    104             var dictionary = result as IDictionary<stringobject>;
    105             if (dictionary != null)
    106             {
    107                 result = new DynamicJsonObject(dictionary);
    108                 return true;
    109             }
    110 
    111             var arrayList = result as ArrayList;
    112             if (arrayList != null && arrayList.Count > 0)
    113             {
    114                 if (arrayList[0is IDictionary<stringobject>)
    115                     result = new List<object>(arrayList.Cast<IDictionary<stringobject>>().Select(x => new DynamicJsonObject(x)));
    116                 else
    117                     result = new List<object>(arrayList.Cast<object>());
    118             }
    119 
    120             return true;
    121         }
    122     }
    123 
    124     #endregion
    125 }

    You can use it like this:

    View Code
    1 string json = ...;
    2 
    3 var serializer = new JavaScriptSerializer();
    4 serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
    5 
    6 dynamic obj = serializer.Deserialize(json, typeof(object));

    So, given a JSON string: 

     

    View Code
    1 {
    2   "Items":[
    3     { "Name":"Apple""Price":12.3 },
    4     { "Name":"Grape""Price":3.21 }
    5   ],
    6   "Date":"21/11/2010"
    7 }

    The following code will work at runtime:

     

    View Code
    1 var data = serializer.Deserialize(json, typeof(object));
    2 
    3 data.Date; // "21/11/2010"
    4 data.Items.Count; // 2
    5 data.Items[0].Name; // "Apple"
    6 data.Items[0].Price; // 12.3 (as a decimal)
    7 data.Items[1].Name; // "Grape"
    8 data.Items[1].Price; // 3.21 (as a decimal)

    I'm interested in any discussion about this approach.

    EDIT

    I updated the code to fix a small bug (with lists of complex types) and to include a ToString method that outputs the JSON string, which I found useful for debugging. You can drop the two methods out if you don't want them as they aren't required for deserialisation.

    It's pretty simple using Newtonsoft.Json:

    View Code
    1 var jsonSerializer = new JsonSerializer();
    2 dynamic stuff = jsonSerializer.Deserialize(new JsonTextReader(new StringReader("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }")));
    3 
    4 var name = stuff.Name;
    5 var address = stuff.Address.City;

    .Net 4.0 has a built-in library to do this:

    View Code
    1 using System.Web.Script.Serialization;
    2 JavaScriptSerializer jss = new JavaScriptSerializer();
    3 var d=jss.Deserialize<dynamic>(str);

    This is the simplest way You can use it like this:

    View Code
    1  (new System.Collections.Generic.Mscorlib_DictionaryDebugView<string,object>(((System.Collections.Generic.Dictionary<string,object>)(obj[0])))).Items[1]

    refer to:

    http://stackoverflow.com/questions/3142495/deserialize-json-into-c-sharp-dynamic-object

    这有一篇介绍动态解析原理的文章:http://www.codeproject.com/Articles/349646/Dynamic-JSON-parser

  • 相关阅读:
    纯CSS实现“流星赶月”
    移动端web开发与适应之媒体查询
    VSCode 代码格式化,如何解决 Vetur 与 ESLint 的冲突?
    前端图片等比例缩放方案
    Vue的生命周期的详解
    JS第七种数据类型Symbol详解
    微信小程序页面自适应
    【源码学习】Vue初始化过程 (附思维导图)
    springboot 整合 elasticsearch + kibana (使用框架 api 方式操作 es 的 crud)
    使用一台电脑连接另一台安装有虚拟机的电脑里面的虚拟机方法
  • 原文地址:https://www.cnblogs.com/tewuapple/p/2685271.html
Copyright © 2020-2023  润新知