.NET(C#) Json字符串反序列化成dynamic类型对象的方法代码

.NET (C#) 中,可以使用Json 库 来将 JSON 字符串反序列化为动态类型 (dynamic) 的对象。 dynamic 类型使得我们可以在运行时动态访问 JSON 数据的属性,而不需要定义强类型的类。本文主要介绍.NET(C#)中,将Json字符串反序列化(Deserialize)时,反序列化(Deserialize)成动态类型(dynamic类型)对象的五种方法和代码。

1、使用Json.NET实现

可以使用 Json.NET(也称为 Newtonsoft.Json)来将 JSON 字符串反序列化为 dynamic 类型对象。 Json.NET 是一个非常流行的 JSON 处理库,它支持强类型和动态类型的反序列化。

文档https://www.newtonsoft.com/json/help/html/QueryJsonDynamic.htm

dynamic stuff = JsonConvert.DeserializeObject("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");
string name = stuff.Name;
string address = stuff.Address.City;

//using Newtonsoft.Json.Linq
dynamic stuff = JObject.Parse("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");
string name = stuff.Name;
string address = stuff.Address.City;

2、使用System.Web.Helpers.Json实现

文档System.Web.Helpers.Json

包含在System.Web.Helpers程序集(.NET 4.0)中。使用 System.Web.Helpers.Json 来反序列化 JSON 字符串为 dynamic 类型对象的方法非常简单。System.Web.Helpers.Json 提供了静态方法 Json.Decode,可以将 JSON 字符串解析为 dynamic 类型的对象。

var dynamicObject = Json.Decode("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");
string name = stuff.Name;
string address = stuff.Address.City;

3、使用JavaScriptSerializer实现

.Net 4.0内置的一个库,可以使用 JavaScriptSerializer 类将 JSON 字符串反序列化为动态类型(dynamic)对象。JavaScriptSerializer 是一个简单的内置工具,适用于较小的 JSON 数据反序列化。

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

using System.Web.Script.Serialization;
WebClient client = new WebClient();
string getString = client.DownloadString("https://graph.facebook.com/zuck");
JavaScriptSerializer serializer = new JavaScriptSerializer();
dynamic item = serializer.Deserialize<object>(getString);
string name = item["name"];

4、使用JsonFx实现

使用 JsonFx 将 JSON 字符串反序列化为 dynamic 类型的对象可以通过 JsonReader 实现。

文档https://github.com/jsonfx/jsonfx

var reader = new JsonReader(); var writer = new JsonWriter();
string input = @"{ ""foo"": true, ""array"": [ 42, false, ""Hello!"", null ] }";
dynamic output = reader.Read(input);
Console.WriteLine(output.array[0]); // 42
string json = writer.Write(output);
Console.WriteLine(json); // {"foo":true,"array":[42,false,"Hello!",null]}

5、使用自定义DynamicJsonConverter类实现

需要引用System.Web.Extensions,要将 JSON 字符串反序列化为 dynamic 类型的对象,可以通过自定义一个 DynamicJsonConverter 来实现。这个自定义的转换器可以与 JsonSerializer 一起使用。

DynamicJsonConverter类代码

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Web.Script.Serialization;
public sealed class DynamicJsonConverter : JavaScriptConverter
{
    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        if (dictionary == null)
            throw new ArgumentNullException("dictionary");
        return type == typeof(object) ? new DynamicJsonObject(dictionary) : null;
    }
    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        throw new NotImplementedException();
    }
    public override IEnumerable<Type> SupportedTypes
    {
        get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(object) })); }
    }
    private sealed class DynamicJsonObject : DynamicObject
    {
        private readonly IDictionary<string, object> _dictionary;
        public DynamicJsonObject(IDictionary<string, object> dictionary)
        {
            if (dictionary == null)
                throw new ArgumentNullException("dictionary");
            _dictionary = dictionary;
        }
        public override string ToString()
        {
            var sb = new StringBuilder("{");
            ToString(sb);
            return sb.ToString();
        }
        private void ToString(StringBuilder sb)
        {
            var firstInDictionary = true;
            foreach (var pair in _dictionary)
            {
                if (!firstInDictionary)
                    sb.Append(",");
                firstInDictionary = false;
                var value = pair.Value;
                var name = pair.Key;
                if (value is string)
                {
                    sb.AppendFormat("{0}:\"{1}\"", name, value);
                }
                else if (value is IDictionary<string, object>)
                {
                    new DynamicJsonObject((IDictionary<string, object>)value).ToString(sb);
                }
                else if (value is ArrayList)
                {
                    sb.Append(name + ":[");
                    var firstInArray = true;
                    foreach (var arrayValue in (ArrayList)value)
                    {
                        if (!firstInArray)
                            sb.Append(",");
                        firstInArray = false;
                        if (arrayValue is IDictionary<string, object>)
                            new DynamicJsonObject((IDictionary<string, object>)arrayValue).ToString(sb);
                        else if (arrayValue is string)
                            sb.AppendFormat("\"{0}\"", arrayValue);
                        else
                            sb.AppendFormat("{0}", arrayValue);
                    }
                    sb.Append("]");
                }
                else
                {
                    sb.AppendFormat("{0}:{1}", name, value);
                }
            }
            sb.Append("}");
        }
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (!_dictionary.TryGetValue(binder.Name, out result))
            {
                // return null to avoid exception.  caller can check for null this way...
                result = null;
                return true;
            }
            result = WrapResultObject(result);
            return true;
        }
        public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
        {
            if (indexes.Length == 1 && indexes[0] != null)
            {
                if (!_dictionary.TryGetValue(indexes[0].ToString(), out result))
                {
                    // return null to avoid exception.  caller can check for null this way...
                    result = null;
                    return true;
                }
                result = WrapResultObject(result);
                return true;
            }
            return base.TryGetIndex(binder, indexes, out result);
        }
        private static object WrapResultObject(object result)
        {
            var dictionary = result as IDictionary<string, object>;
            if (dictionary != null)
                return new DynamicJsonObject(dictionary);
            var arrayList = result as ArrayList;
            if (arrayList != null && arrayList.Count > 0)
            {
                return arrayList[0] is IDictionary<string, object> 
                    ? new List<object>(arrayList.Cast<IDictionary<string, object>>().Select(x => new DynamicJsonObject(x))) 
                    : new List<object>(arrayList.Cast<object>());
            }
            return result;
        }
    }
}

使用示例代码

dynamic data = serializer.Deserialize("{ \"Items\":[ { \"Name\":\"Apple\", \"Price\":12.3 }, { \"Name\":\"Grape\", \"Price\":3.21 } ], \"Date\":\"21/11/2010\" }", typeof(object));

data.Date; // "21/11/2010"
data.Items.Count; // 2
data.Items[0].Name; // "Apple"
data.Items[0].Price; // 12.3 (as a decimal)
data.Items[1].Name; // "Grape"
data.Items[1].Price; // 3.21 (as a decimal)

推荐阅读
cjavapy编程之路首页