zoukankan      html  css  js  c++  java
  • DynamicJson

    json字符串解析成Dynamic对象,开源地址http://dynamicjson.codeplex.com/,访问比较慢。使用方法摘录如下:

     Project Description
    dynamic json structure for C# 4.0. 

    Features

      • Intuitive operation by "dynamic".
      • This library is only 1 class and written in 400 lines.
      • Available in NuGet Install-Package DynamicJson

    Read and Access

    // Parse (from JsonString to DynamicJson)
    var json = DynamicJson.Parse(@"{""foo"":""json"", ""bar"":100, ""nest"":{ ""foobar"":true } }");
    
    var r1 = json.foo; // "json" - dynamic(string)
    var r2 = json.bar; // 100 - dynamic(double)
    var r3 = json.nest.foobar; // true - dynamic(bool)
    var r4 = json["nest"]["foobar"]; // can access indexer
    

    Operate

    var json = DynamicJson.Parse(@"{""foo"":""json"", ""bar"":100, ""nest"":{ ""foobar"":true } }");
    
    // Check Defined Peroperty
    // .name() is shortcut of IsDefined("name")
    var b1_1 = json.IsDefined("foo"); // true
    var b2_1 = json.IsDefined("foooo"); // false
    var b1_2 = json.foo(); // true            
    var b2_2 = json.foooo(); // false;
    
    // Add
    json.Arr = new string[] { "NOR", "XOR" }; // Add Array
    json.Obj1 = new { }; // Add Object
    json.Obj2 = new { foo = "abc", bar = 100 }; // Add and Init
    
    // Delete
    // ("name") is shortcut of Delete("name")
    json.Delete("foo");
    json.Arr.Delete(0);
    json("bar");
    json.Arr(1);
    
    // Replace
    json.Obj1 = 5000;
    
    // Create New JsonObject
    dynamic newjson = new DynamicJson();
    newjson.str = "aaa";
    newjson.obj = new { foo = "bar" };
    
    // Serialize(to JSON String)
    var jsonstring = newjson.ToString(); // {"str":"aaa","obj":{"foo":"bar"}}
    

    Enumerate

    // DynamicJson - (IsArray)
    var arrayJson = DynamicJson.Parse(@"[1,10,200,300]");
    foreach (int item in arrayJson)
    {
        Console.WriteLine(item); // 1, 10, 200, 300
    }
    
    // DynamicJson - (IsObject)
    var objectJson = DynamicJson.Parse(@"{""foo"":""json"",""bar"":100}");
    foreach (KeyValuePair<string, dynamic> item in objectJson)
    {
        Console.WriteLine(item.Key + ":" + item.Value); // foo:json, bar:100
    }
    

    Convert/Deserialize

    public class FooBar
    {
        public string foo { get; set; }
        public int bar { get; set; }
    }
    
    var arrayJson = DynamicJson.Parse(@"[1,10,200,300]");
    var objectJson = DynamicJson.Parse(@"{""foo"":""json"",""bar"":100}");
    
    // (type) is shortcut of Deserialize<type>()
    var array1 = arrayJson.Deserialize<int[]>();
    var array2 = (int[])arrayJson; // equals array1
    int[] array3 = arrayJson; // equals array2
    
    // mapping by public property name
    var foobar1 = objectJson.Deserialize<FooBar>();
    var foobar2 = (FooBar)objectJson;
    FooBar foobar3 = objectJson;
    
    // with linq
    var objectJsonList = DynamicJson.Parse(@"[{""bar"":50},{""bar"":100}]");
    var barSum = ((FooBar[])objectJsonList).Select(fb => fb.bar).Sum(); // 150
    var dynamicWithLinq = ((dynamic[])objectJsonList).Select(d => d.bar);
    

    Serialize (to JSON String from Object)

    // Serialize (from Object to JsonString)
    var obj = new
    {
        Name = "Foo",
        Age = 30,
        Address = new
        {
            Country = "Japan",
            City = "Tokyo"
        },
        Like = new[] { "Microsoft", "Xbox" }
    };
    // {"Name":"Foo","Age":30,"Address":{"Country":"Japan","City":"Tokyo"},"Like":["Microsoft","Xbox"]}
    var jsonStringFromObj = DynamicJson.Serialize(obj);
    
    // [{"foo":"fooooo!","bar":1000},{"foo":"orz","bar":10}]
    var foobar = new FooBar[] { 
            new FooBar { foo = "fooooo!", bar = 1000 }, 
            new FooBar { foo = "orz", bar = 10 } };
    var jsonFoobar = DynamicJson.Serialize(foobar);
    

    Notice: corner case

    var nestJson = DynamicJson.Parse(@"{""tes"":10,""nest"":{""a"":0}");
    
    nestJson.nest(); // This equals json.IsDefined("nest")
    nestJson.nest("a"); // This equals json.nest.Delete("a")
    
    // if name is C#'s reserved word then put prefix "@"
    var json = DynamicJson.Parse(@"{""int"":10,""event"":null}");
    var r1 = json.@int; // 10.0
    var r2 = json.@event; // null
    

    Example : TwitterAPI

    static void Main()
    {
        var publicTL = new WebClient().DownloadString(@"http://twitter.com/statuses/public_timeline.json");
        var statuses = DynamicJson.Parse(publicTL);
        foreach (var status in statuses)
        {
            Console.WriteLine(status.user.screen_name);
            Console.WriteLine(status.text);
        }
    }
    

    Example : TwitterAPI2

    static void Main(string[] args)
    {
        // fetch and flatten user_timeline
        var wc = new WebClient();
        var statuses = Enumerable.Range(1, 5)
            .Select(i =>
                wc.DownloadString("http://twitter.com/statuses/user_timeline/neuecc.json?page=" + i))
            .SelectMany(s => (dynamic[])DynamicJson.Parse(s))
            .OrderBy(j => j.id);
    
        foreach (var status in statuses)
        {
            Console.WriteLine(status.text);
        }
    }

    实际应用 :微信Web版通讯录解析

    调用微信接口返回的通讯录数据格式 

    {
    "BaseResponse": {
    "Ret": 0,
    "ErrMsg": ""
    }
    ,
    "MemberCount": 246,
    "MemberList": [{
    "Uin": 0,
    "UserName": "@48150c1c772dea6fc78adc0704bb45ae",
    "NickName": "木春",
    "HeadImgUrl": "/cgi-bin/mmwebwx-bin/webwxgeticon?seq=500719&username=@48150c1c772dea6fc78adc0704bb45ae&skey=",
    "ContactFlag": 3,
    "MemberCount": 0,
    "MemberList": [],
    "RemarkName": "",
    "HideInputBarFlag": 0,
    "Sex": 0,
    "Signature": "",
    "VerifyFlag": 0,
    "OwnerUin": 0,
    "PYInitial": "MC",
    "PYQuanPin": "muchun",
    "RemarkPYInitial": "",
    "RemarkPYQuanPin": "",
    "StarFriend": 0,
    "AppAccountFlag": 0,
    "Statues": 0,
    "AttrStatus": 98489,
    "Province": "北京",
    "City": "",
    "Alias": "",
    "SnsFlag": 0,
    "UniFriend": 0,
    "DisplayName": "",
    "ChatRoomId": 0,
    "KeyWord": "Col",
    "EncryChatRoomId": ""
    }
    ,{
    "Uin": 0,
    "UserName": "@fd853d9befbee535976cfbad99b84c20",
    "NickName": "敷衍",
    "HeadImgUrl": "/cgi-bin/mmwebwx-bin/webwxgeticon?seq=1343690&username=@fd853d9befbee535976cfbad99b84c20&skey=",
    "ContactFlag": 1,
    "MemberCount": 0,
    "MemberList": [],
    "RemarkName": "",
    "HideInputBarFlag": 0,
    "Sex": 2,
    "Signature": "",
    "VerifyFlag": 0,
    "OwnerUin": 0,
    "PYInitial": "FY",
    "PYQuanPin": "fuyan",
    "RemarkPYInitial": "",
    "RemarkPYQuanPin": "",
    "StarFriend": 0,
    "AppAccountFlag": 0,
    "Statues": 0,
    "AttrStatus": 4147,
    "Province": "北京",
    "City": "海淀",
    "Alias": "",
    "SnsFlag": 17,
    "UniFriend": 0,
    "DisplayName": "",
    "ChatRoomId": 0,
    "KeyWord": "G23",
    "EncryChatRoomId": ""
    }
    ]
    }
    通讯录JSON数据

    解析成对象列表

            public static List<ContactModel> GetContactList(string response)
            {
    
                var ret = new List<ContactModel>();
    
                var contactJson = DynamicJson.Parse(response);
                foreach (var member in contactJson.MemberList)
                {
                    var model = new ContactModel()
                    {
                        UserName = member.UserName,
                        NickName = member.NickName,
                        HeadImgUrl = member.HeadImgUrl,
                        RemarkName = member.RemarkName,
                        Sex = member.Sex,
                        Signature = member.Signature,
                        VerifyFlag = member.VerifyFlag,
                        Province = member.Province,
                        City = member.City,
                    };
                    ret.Add(model);
                }
                return ret;
            }

    属性直接访问就行,注意大小写。最后奉上DynamicJson.cs的完整代码

    /*--------------------------------------------------------------------------
    * DynamicJson
    * ver 1.2.0.0 (May. 21th, 2010)
    *
    * created and maintained by neuecc <ils@neue.cc>
    * licensed under Microsoft Public License(Ms-PL)
    * http://neue.cc/
    * http://dynamicjson.codeplex.com/
     * 博客园网友 夜の魔王 友情借用此代码,用于微信开发。
     * http://www.cnblogs.com/deepleo/
    *--------------------------------------------------------------------------*/
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Dynamic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Runtime.Serialization.Json;
    using System.Text;
    using System.Xml;
    using System.Xml.Linq;
    
    namespace WeiXin.Manager.Helper
    
    {
        public class DynamicJson : DynamicObject
        {
            private enum JsonType
            {
                @string, number, boolean, @object, array, @null
            }
    
            // public static methods
    
            /// <summary>from JsonSring to DynamicJson</summary>
            public static dynamic Parse(string json)
            {
                return Parse(json, Encoding.Unicode);
            }
    
            /// <summary>from JsonSring to DynamicJson</summary>
            public static dynamic Parse(string json, Encoding encoding)
            {
                using (var reader = JsonReaderWriterFactory.CreateJsonReader(encoding.GetBytes(json), XmlDictionaryReaderQuotas.Max))
                {
                    return ToValue(XElement.Load(reader));
                }
            }
    
            /// <summary>from JsonSringStream to DynamicJson</summary>
            public static dynamic Parse(Stream stream)
            {
                using (var reader = JsonReaderWriterFactory.CreateJsonReader(stream, XmlDictionaryReaderQuotas.Max))
                {
                    return ToValue(XElement.Load(reader));
                }
            }
    
            /// <summary>from JsonSringStream to DynamicJson</summary>
            public static dynamic Parse(Stream stream, Encoding encoding)
            {
                using (var reader = JsonReaderWriterFactory.CreateJsonReader(stream, encoding, XmlDictionaryReaderQuotas.Max, _ => { }))
                {
                    return ToValue(XElement.Load(reader));
                }
            }
    
            /// <summary>create JsonSring from primitive or IEnumerable or Object({public property name:property value})</summary>
            public static string Serialize(object obj)
            {
                return CreateJsonString(new XStreamingElement("root", CreateTypeAttr(GetJsonType(obj)), CreateJsonNode(obj)));
            }
    
            // private static methods
    
            private static dynamic ToValue(XElement element)
            {
                var type = (JsonType)Enum.Parse(typeof(JsonType), element.Attribute("type").Value);
                switch (type)
                {
                    case JsonType.boolean:
                        return (bool)element;
                    case JsonType.number:
                        return (double)element;
                    case JsonType.@string:
                        return (string)element;
                    case JsonType.@object:
                    case JsonType.array:
                        return new DynamicJson(element, type);
                    case JsonType.@null:
                    default:
                        return null;
                }
            }
    
            private static JsonType GetJsonType(object obj)
            {
                if (obj == null) return JsonType.@null;
    
                switch (Type.GetTypeCode(obj.GetType()))
                {
                    case TypeCode.Boolean:
                        return JsonType.boolean;
                    case TypeCode.String:
                    case TypeCode.Char:
                    case TypeCode.DateTime:
                        return JsonType.@string;
                    case TypeCode.Int16:
                    case TypeCode.Int32:
                    case TypeCode.Int64:
                    case TypeCode.UInt16:
                    case TypeCode.UInt32:
                    case TypeCode.UInt64:
                    case TypeCode.Single:
                    case TypeCode.Double:
                    case TypeCode.Decimal:
                    case TypeCode.SByte:
                    case TypeCode.Byte:
                        return JsonType.number;
                    case TypeCode.Object:
                        return (obj is IEnumerable) ? JsonType.array : JsonType.@object;
                    case TypeCode.DBNull:
                    case TypeCode.Empty:
                    default:
                        return JsonType.@null;
                }
            }
    
            private static XAttribute CreateTypeAttr(JsonType type)
            {
                return new XAttribute("type", type.ToString());
            }
    
            private static object CreateJsonNode(object obj)
            {
                var type = GetJsonType(obj);
                switch (type)
                {
                    case JsonType.@string:
                    case JsonType.number:
                        return obj;
                    case JsonType.boolean:
                        return obj.ToString().ToLower();
                    case JsonType.@object:
                        return CreateXObject(obj);
                    case JsonType.array:
                        return CreateXArray(obj as IEnumerable);
                    case JsonType.@null:
                    default:
                        return null;
                }
            }
    
            private static IEnumerable<XStreamingElement> CreateXArray<T>(T obj) where T : IEnumerable
            {
                return obj.Cast<object>()
                    .Select(o => new XStreamingElement("item", CreateTypeAttr(GetJsonType(o)), CreateJsonNode(o)));
            }
    
            private static IEnumerable<XStreamingElement> CreateXObject(object obj)
            {
                return obj.GetType()
                    .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                    .Select(pi => new { Name = pi.Name, Value = pi.GetValue(obj, null) })
                    .Select(a => new XStreamingElement(a.Name, CreateTypeAttr(GetJsonType(a.Value)), CreateJsonNode(a.Value)));
            }
    
            private static string CreateJsonString(XStreamingElement element)
            {
                using (var ms = new MemoryStream())
                using (var writer = JsonReaderWriterFactory.CreateJsonWriter(ms, Encoding.Unicode))
                {
                    element.WriteTo(writer);
                    writer.Flush();
                    return Encoding.Unicode.GetString(ms.ToArray());
                }
            }
    
            // dynamic structure represents JavaScript Object/Array
    
            readonly XElement xml;
            readonly JsonType jsonType;
    
            /// <summary>create blank JSObject</summary>
            public DynamicJson()
            {
                xml = new XElement("root", CreateTypeAttr(JsonType.@object));
                jsonType = JsonType.@object;
            }
    
            private DynamicJson(XElement element, JsonType type)
            {
                Debug.Assert(type == JsonType.array || type == JsonType.@object);
    
                xml = element;
                jsonType = type;
            }
    
            public bool IsObject { get { return jsonType == JsonType.@object; } }
    
            public bool IsArray { get { return jsonType == JsonType.array; } }
    
            /// <summary>has property or not</summary>
            public bool IsDefined(string name)
            {
                return IsObject && (xml.Element(name) != null);
            }
    
            /// <summary>has property or not</summary>
            public bool IsDefined(int index)
            {
                return IsArray && (xml.Elements().ElementAtOrDefault(index) != null);
            }
    
            /// <summary>delete property</summary>
            public bool Delete(string name)
            {
                var elem = xml.Element(name);
                if (elem != null)
                {
                    elem.Remove();
                    return true;
                }
                else return false;
            }
    
            /// <summary>delete property</summary>
            public bool Delete(int index)
            {
                var elem = xml.Elements().ElementAtOrDefault(index);
                if (elem != null)
                {
                    elem.Remove();
                    return true;
                }
                else return false;
            }
    
            /// <summary>mapping to Array or Class by Public PropertyName</summary>
            public T Deserialize<T>()
            {
                return (T)Deserialize(typeof(T));
            }
    
            private object Deserialize(Type type)
            {
                return (IsArray) ? DeserializeArray(type) : DeserializeObject(type);
            }
    
            private dynamic DeserializeValue(XElement element, Type elementType)
            {
                var value = ToValue(element);
                if (value is DynamicJson)
                {
                    value = ((DynamicJson)value).Deserialize(elementType);
                }
                return Convert.ChangeType(value, elementType);
            }
    
            private object DeserializeObject(Type targetType)
            {
                var result = Activator.CreateInstance(targetType);
                var dict = targetType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                    .Where(p => p.CanWrite)
                    .ToDictionary(pi => pi.Name, pi => pi);
                foreach (var item in xml.Elements())
                {
                    PropertyInfo propertyInfo;
                    if (!dict.TryGetValue(item.Name.LocalName, out propertyInfo)) continue;
                    var value = DeserializeValue(item, propertyInfo.PropertyType);
                    propertyInfo.SetValue(result, value, null);
                }
                return result;
            }
    
            private object DeserializeArray(Type targetType)
            {
                if (targetType.IsArray) // Foo[]
                {
                    var elemType = targetType.GetElementType();
                    dynamic array = Array.CreateInstance(elemType, xml.Elements().Count());
                    var index = 0;
                    foreach (var item in xml.Elements())
                    {
                        array[index++] = DeserializeValue(item, elemType);
                    }
                    return array;
                }
                else // List<Foo>
                {
                    var elemType = targetType.GetGenericArguments()[0];
                    dynamic list = Activator.CreateInstance(targetType);
                    foreach (var item in xml.Elements())
                    {
                        list.Add(DeserializeValue(item, elemType));
                    }
                    return list;
                }
            }
    
            // Delete
            public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
            {
                result = (IsArray)
                    ? Delete((int)args[0])
                    : Delete((string)args[0]);
                return true;
            }
    
            // IsDefined, if has args then TryGetMember
            public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
            {
                if (args.Length > 0)
                {
                    result = null;
                    return false;
                }
    
                result = IsDefined(binder.Name);
                return true;
            }
    
            // Deserialize or foreach(IEnumerable)
            public override bool TryConvert(ConvertBinder binder, out object result)
            {
                if (binder.Type == typeof(IEnumerable) || binder.Type == typeof(object[]))
                {
                    var ie = (IsArray)
                        ? xml.Elements().Select(x => ToValue(x))
                        : xml.Elements().Select(x => (dynamic)new KeyValuePair<string, object>(x.Name.LocalName, ToValue(x)));
                    result = (binder.Type == typeof(object[])) ? ie.ToArray() : ie;
                }
                else
                {
                    result = Deserialize(binder.Type);
                }
                return true;
            }
    
            private bool TryGet(XElement element, out object result)
            {
                if (element == null)
                {
                    result = null;
                    return false;
                }
    
                result = ToValue(element);
                return true;
            }
    
            public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
            {
                return (IsArray)
                    ? TryGet(xml.Elements().ElementAtOrDefault((int)indexes[0]), out result)
                    : TryGet(xml.Element((string)indexes[0]), out result);
            }
    
            public override bool TryGetMember(GetMemberBinder binder, out object result)
            {
                return (IsArray)
                    ? TryGet(xml.Elements().ElementAtOrDefault(int.Parse(binder.Name)), out result)
                    : TryGet(xml.Element(binder.Name), out result);
            }
    
            private bool TrySet(string name, object value)
            {
                var type = GetJsonType(value);
                var element = xml.Element(name);
                if (element == null)
                {
                    xml.Add(new XElement(name, CreateTypeAttr(type), CreateJsonNode(value)));
                }
                else
                {
                    element.Attribute("type").Value = type.ToString();
                    element.ReplaceNodes(CreateJsonNode(value));
                }
    
                return true;
            }
    
            private bool TrySet(int index, object value)
            {
                var type = GetJsonType(value);
                var e = xml.Elements().ElementAtOrDefault(index);
                if (e == null)
                {
                    xml.Add(new XElement("item", CreateTypeAttr(type), CreateJsonNode(value)));
                }
                else
                {
                    e.Attribute("type").Value = type.ToString();
                    e.ReplaceNodes(CreateJsonNode(value));
                }
    
                return true;
            }
    
            public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
            {
                return (IsArray)
                    ? TrySet((int)indexes[0], value)
                    : TrySet((string)indexes[0], value);
            }
    
            public override bool TrySetMember(SetMemberBinder binder, object value)
            {
                return (IsArray)
                    ? TrySet(int.Parse(binder.Name), value)
                    : TrySet(binder.Name, value);
            }
    
            public override IEnumerable<string> GetDynamicMemberNames()
            {
                return (IsArray)
                    ? xml.Elements().Select((x, i) => i.ToString())
                    : xml.Elements().Select(x => x.Name.LocalName);
            }
    
            /// <summary>Serialize to JsonString</summary>
            public override string ToString()
            {
                // <foo type="null"></foo> is can't serialize. replace to <foo type="null" />
                foreach (var elem in xml.Descendants().Where(x => x.Attribute("type").Value == "null"))
                {
                    elem.RemoveNodes();
                }
                return CreateJsonString(new XStreamingElement("root", CreateTypeAttr(jsonType), xml.Elements()));
            }
        }
    }
    1.2.0.0
  • 相关阅读:
    linux之awk命令
    HDU 2097 Sky数 进制转换
    HDU 2077 汉诺塔IV
    HDU 2094 产生冠军 dfs加map容器
    HDU 2073 叠框
    HDU 2083 简易版之最短距离
    HDU 2063 过山车 二分匹配
    天梯 1014 装箱问题
    天梯 1214 线段覆盖
    天梯 1098 均分纸牌
  • 原文地址:https://www.cnblogs.com/zhaobl/p/DynamicJson.html
Copyright © 2011-2022 走看看