首页 文章

将JSON反序列化为C#动态对象?

提问于
浏览
822

有没有办法将JSON内容反序列化为C#4动态类型?为了使用DataContractJsonSerializer,跳过创建一堆类会很不错 .

24 回答

  • 587

    最简单的方法是

    只是包括这个dll

    使用这样的代码

    dynamic json = new JDynamic("{a:'abc'}");
    //json.a is a string "abc"
    
    dynamic json = new JDynamic("{a:3.1416}");
    //json.a is 3.1416m
    
    dynamic json = new JDynamic("{a:1}");
    //json.a is
    
    dynamic json = new JDynamic("[1,2,3]");
    /json.Length/json.Count is 3
    //And you can use json[0]/ json[2] to get the elements
    
    dynamic json = new JDynamic("{a:[1,2,3]}");
    //json.a.Length /json.a.Count is 3.
    //And you can use  json.a[0]/ json.a[2] to get the elements
    
    dynamic json = new JDynamic("[{b:1},{c:1}]");
    //json.Length/json.Count is 2.
    //And you can use the  json[0].b/json[1].c to get the num.
    
  • 7

    有一个名为SimpleJson的C#轻量级json库,可以在http://simplejson.codeplex.com找到https://github.com/facebook-csharp-sdk/simple-json

    它支持.net 3.5,silverlight和windows phone 7 .

    支持.net 4.0的动态

    也可以作为nuget包安装

    Install-Package SimpleJson
    
  • 4

    如果您乐意依赖 System.Web.Helpers 程序集,则可以使用Json类:

    dynamic data = Json.Decode(json);
    

    它作为.NET 4框架的additional download包含在MVC框架中 . 如果有帮助,一定要给Vlad一个upvote!但是,如果您不能假设客户端环境包含此DLL,请继续阅读 .


    建议采用另一种反序列化方法here . 我稍微修改了代码以修复错误并适合我的编码风格 . 您只需要此代码以及项目中对 System.Web.Extensions 的引用:

    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) })); }
        }
    
        #region Nested type: DynamicJsonObject
    
        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;
            }
        }
    
        #endregion
    }
    

    你可以像这样使用它:

    string json = ...;
    
    var serializer = new JavaScriptSerializer();
    serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
    
    dynamic obj = serializer.Deserialize(json, typeof(object));
    

    所以,给定一个JSON字符串:

    {
      "Items":[
        { "Name":"Apple", "Price":12.3 },
        { "Name":"Grape", "Price":3.21 }
      ],
      "Date":"21/11/2010"
    }
    

    以下代码将在运行时运行:

    dynamic data = serializer.Deserialize(json, 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)
    
  • 4

    试试这个 -

    var units = new { Name = "Phone", Color= "White" };
        var jsonResponse = JsonConvert.DeserializeAnonymousType(json, units );
    
  • 523

    为此,我将使用JSON.NET对JSON流进行低级解析,然后从 ExpandoObject 类的实例中构建对象层次结构 .

  • 3

    使用包含在该库中的 JObject 类可以动态地反序列化JSON.NET . 我的JSON字符串代表这些类:

    public class Foo {
       public int Age {get;set;}
       public Bar Bar {get;set;}
    }
    
    public class Bar {
       public DateTime BDay {get;set;}
    }
    

    现在我们反序列化字符串而不引用上面的类:

    var dyn = JsonConvert.DeserializeObject<JObject>(jsonAsFooString);
    
    JProperty propAge = dyn.Properties().FirstOrDefault(i=>i.Name == "Age");
    if(propAge != null) {
        int age = int.Parse(propAge.Value.ToString());
        Console.WriteLine("age=" + age);
    }
    
    //or as a one-liner:
    int myage = int.Parse(dyn.Properties().First(i=>i.Name == "Age").Value.ToString());
    

    或者如果你想更深入:

    var propBar = dyn.Properties().FirstOrDefault(i=>i.Name == "Bar");
    if(propBar != null) {
        JObject o = (JObject)propBar.First();
        var propBDay = o.Properties().FirstOrDefault (i => i.Name=="BDay");
        if(propBDay != null) {
            DateTime bday = DateTime.Parse(propBDay.Value.ToString());
            Console.WriteLine("birthday=" + bday.ToString("MM/dd/yyyy"));
        }
    }
    
    //or as a one-liner:
    DateTime mybday = DateTime.Parse(((JObject)dyn.Properties().First(i=>i.Name == "Bar").First()).Properties().First(i=>i.Name == "BDay").Value.ToString());
    

    有关完整示例,请参阅post .

  • 0

    您可以扩展JavaScriptSerializer以递归方式将它创建的字典复制到expando对象,然后动态使用它们:

    static class JavaScriptSerializerExtensions
    {
        public static dynamic DeserializeDynamic(this JavaScriptSerializer serializer, string value)
        {
            var dictionary = serializer.Deserialize<IDictionary<string, object>>(value);
            return GetExpando(dictionary);
        }
    
        private static ExpandoObject GetExpando(IDictionary<string, object> dictionary)
        {
            var expando = (IDictionary<string, object>)new ExpandoObject();
    
            foreach (var item in dictionary)
            {
                var innerDictionary = item.Value as IDictionary<string, object>;
                if (innerDictionary != null)
                {
                    expando.Add(item.Key, GetExpando(innerDictionary));
                }
                else
                {
                    expando.Add(item.Key, item.Value);
                }
            }
    
            return (ExpandoObject)expando;
        }
    }
    

    然后你只需要为你定义扩展的命名空间使用using语句(考虑在System.Web.Script.Serialization中定义它们...另一个技巧是不使用命名空间,那么你不需要使用完全声明)你可以像这样消费它们:

    var serializer = new JavaScriptSerializer();
    var value = serializer.DeserializeDynamic("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");
    
    var name = (string)value.Name; // Jon Smith
    var age = (int)value.Age;      // 42
    
    var address = value.Address;
    var city = (string)address.City;   // New York
    var state = (string)address.State; // NY
    
  • 2

    使用Json.NET非常简单:

    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;
    

    文件: Querying JSON with dynamic

  • 72

    看看我在CodeProject上写的文章,它正是回答了这个问题:

    Dynamic types with JSON.NET

    在这里重新发布所有内容的方式太多了,甚至更少,因为该文章附带了密钥/所需的源文件 .

  • 14

    要获得ExpandoObject:

    using Newtonsoft.Json;
    using Newtonsoft.Json.Converters;
    
    Container container = JsonConvert.Deserialize<Container>(jsonAsString, new ExpandoObjectConverter());
    
  • 5

    如何使用动态和JavaScriptSerializer解析easy json

    请添加 System.Web.Extensions 的引用,并在顶部添加此命名空间 using System.Web.Script.Serialization;

    public static void EasyJson()
    {
        var jsonText = @"{
            ""some_number"": 108.541, 
            ""date_time"": ""2011-04-13T15:34:09Z"", 
            ""serial_number"": ""SN1234""
        }";
    
        var jss = new JavaScriptSerializer();
        var dict = jss.Deserialize<dynamic>(jsonText);
    
        Console.WriteLine(dict["some_number"]); 
        Console.ReadLine();
    }
    

    如何使用动态&JavaScriptSerializer解析嵌套和复杂的json

    请添加 System.Web.Extensions 的引用,并在顶部添加此命名空间 using System.Web.Script.Serialization;

    public static void ComplexJson()
    {
        var jsonText = @"{
            ""some_number"": 108.541, 
            ""date_time"": ""2011-04-13T15:34:09Z"", 
            ""serial_number"": ""SN1234"",
            ""more_data"": {
                ""field1"": 1.0,
                ""field2"": ""hello""
            }
        }";
    
        var jss = new JavaScriptSerializer();
        var dict = jss.Deserialize<dynamic>(jsonText);
    
        Console.WriteLine(dict["some_number"]); 
        Console.WriteLine(dict["more_data"]["field2"]);
        Console.ReadLine();
    }
    
  • 285

    我创建了一个使用Expando Objects的DynamicJsonConverter的新版本 . 我使用了expando对象,因为我想使用Json.net将动态序列化为json .

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Dynamic;
    using System.Web.Script.Serialization;
    
    public static class DynamicJson
    {
        public static dynamic Parse(string json)
        {
            JavaScriptSerializer jss = new JavaScriptSerializer();
            jss.RegisterConverters(new JavaScriptConverter[] { new DynamicJsonConverter() });
    
            dynamic glossaryEntry = jss.Deserialize(json, typeof(object)) as dynamic;
            return glossaryEntry;
        }
    
        class DynamicJsonConverter : JavaScriptConverter
        {
            public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
            {
                if (dictionary == null)
                    throw new ArgumentNullException("dictionary");
    
                var result = ToExpando(dictionary);
    
                return type == typeof(object) ? result : null;
            }
    
            private static ExpandoObject ToExpando(IDictionary<string, object> dictionary)
            {
                var result = new ExpandoObject();
                var dic = result as IDictionary<String, object>;
    
                foreach (var item in dictionary)
                {
                    var valueAsDic = item.Value as IDictionary<string, object>;
                    if (valueAsDic != null)
                    {
                        dic.Add(item.Key, ToExpando(valueAsDic));
                        continue;
                    }
                    var arrayList = item.Value as ArrayList;
                    if (arrayList != null && arrayList.Count > 0)
                    {
                        dic.Add(item.Key, ToExpando(arrayList));
                        continue;
                    }
    
                    dic.Add(item.Key, item.Value);
                }
                return result;
            }
    
            private static ArrayList ToExpando(ArrayList obj)
            {
                ArrayList result = new ArrayList();
    
                foreach (var item in obj)
                {
                    var valueAsDic = item as IDictionary<string, object>;
                    if (valueAsDic != null)
                    {
                        result.Add(ToExpando(valueAsDic));
                        continue;
                    }
    
                    var arrayList = item as ArrayList;
                    if (arrayList != null && arrayList.Count > 0)
                    {
                        result.Add(ToExpando(arrayList));
                        continue;
                    }
    
                    result.Add(item);
                }
                return result;
            }
    
            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) })); }
            }
        }
    }
    
  • 4

    您可以使用System.Web.Helpers.Json执行此操作 - 它的Decode方法返回一个动态对象,您可以根据需要进行遍历 .

    它包含在System.Web.Helpers程序集(.NET 4.0)中 .

    var dynamicObject = Json.Decode(jsonString);
    
  • 77

    .Net 4.0有一个内置库来执行此操作:

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

    这是最简单的方法 .

  • 5

    它可能有点晚了,但是您想要的对象DynamicJSONObject包含在ASP.NET Web Pages包中的System.Web.Helpers.dll中,该包是WebMatrix的一部分 .

  • 6

    简单的“字符串json数据”到没有任何第三方dll的对象

    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"];
    
    //note: JavaScriptSerializer in this namespaces
    //System.Web.Script.Serialization.JavaScriptSerializer
    

    注意:您还可以使用自定义对象 .

    Personel item = serializer.Deserialize<Personel>(getString);
    
  • 4

    JsonFx可以将json反序列化为动态对象 .

    https://github.com/jsonfx/jsonfx

    序列化到/从动态类型(.NET 4.0的默认值):

    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

    使用Newtonsoft.Json的另一种方法:

    dynamic stuff = Newtonsoft.Json.JsonConvert.DeserializeObject("{ color: 'red', value: 5 }");
    string color = stuff.color;
    int value = stuff.value;
    
  • 28

    使用DataSet(C#)使用javascript简单函数创建json流,使用DataSet输入创建json(多表数据集)[[{a:1,b:2,c:3},{a:3,b:5,c :6}],[{A:23,b:45,C:35},{一个:58,b:59,C:45}]]

    只是客户端使用eval例如

    var d = eval('[[{a:1,b:2,c:3},{a:3,b:5,c:6}],[{a:23,b:45,c:35 },{一个:58,b:59,C:45}]]')

    然后用

    d [0] [0] .a //从表0第0行输出1

    d [1] [1] .b //从表1第1行中取出59

    //create by Behnam Mohammadi And Saeed Ahmadian
    public string jsonMini(DataSet ds)
    {
        int t=0, r=0, c=0;
        string stream = "[";
    
        for (t = 0; t < ds.Tables.Count; t++)
        {
            stream += "[";
            for (r = 0; r < ds.Tables[t].Rows.Count; r++)
            {
                stream += "{";
                for (c = 0; c < ds.Tables[t].Columns.Count; c++)
                {
                    stream += ds.Tables[t].Columns[c].ToString() + ":'" + ds.Tables[t].Rows[r][c].ToString() + "',";
                }
                if(c>0)
                    stream = stream.Substring(0, stream.Length - 1);
                stream += "},";
            }
            if(r>0)
                stream = stream.Substring(0, stream.Length - 1);
            stream += "],";
        }
        if(t>0)
            stream = stream.Substring(0, stream.Length - 1);
        stream += "];";
        return stream;
    }
    
  • 4

    你可以用 using Newtonsoft.Json

    var jRoot = 
     JsonConvert.DeserializeObject<dynamic>(Encoding.UTF8.GetString(resolvedEvent.Event.Data));
    

    resolvedEvent.Event.Data 是我从调用核心事件得到的回应 .

  • 4

    使用Cinchoo ETL - 一个可用于将json解析为动态对象的开源库

    string json = @"{
        ""key1"": [
            {
                ""action"": ""open"",
                ""timestamp"": ""2018-09-05 20:46:00"",
                ""url"": null,
                ""ip"": ""66.102.6.98""
            }
        ]
    }";
    using (var p = ChoJSONReader.LoadText(json)
        .WithJSONPath("$.*")
        )
    {
        foreach (var rec in p)
        {
            Console.WriteLine("action: " + rec.action);
            Console.WriteLine("timestamp: " + rec.timestamp);
            Console.WriteLine("url: " + rec.url);
            Console.WriteLine("ip: " + rec.ip);
        }
    }
    

    Output:

    action: open
    timestamp: 2018-09-05 20:46:00
    url: http://www.google.com
    ip: 66.102.6.98
    

    免责声明:我是这个图书馆的作者 .

  • 18

    我在我的代码中使用这样的,它工作正常

    using System.Web.Script.Serialization;
    JavaScriptSerializer oJS = new JavaScriptSerializer();
    RootObject oRootObject = new RootObject();
    oRootObject = oJS.Deserialize<RootObject>(Your JSon String);
    
  • 6

    另一种选择是“将JSON粘贴为类”,以便可以快速轻松地反序列化 .

    • 只需复制整个JSON即可

    • 在VS中:单击编辑>选择性粘贴>将JSON粘贴为类

    这是一个更好的解释n piccas ... https://blogs.msdn.microsoft.com/webdev/2012/12/18/paste-json-as-classes-in-asp-net-and-web-tools-2012-2-rc/

  • 1

    我使用:http://json2csharp.com/来获取表示Json对象的A类 .

    输入:

    {
       "name":"John",
       "age":31,
       "city":"New York",
       "Childs":[
          {
             "name":"Jim",
             "age":11
          },
          {
             "name":"Tim",
             "age":9
          }
       ]
    }
    

    输出:

    public class Child
    {
        public string name { get; set; }
        public int age { get; set; }
    }
    
    public class Person
    {
        public string name { get; set; }
        public int age { get; set; }
        public string city { get; set; }
        public List<Child> Childs { get; set; }
    }
    

    之后我使用Newtonsoft.Json来填充类:

    using Newtonsoft.Json;
    
    namespace GitRepositoryCreator.Common
    {
        class JObjects
        {
            public static string Get(object p_object)
            {
                return JsonConvert.SerializeObject(p_object);
            }
            internal static T Get<T>(string p_object)
            {
                return JsonConvert.DeserializeObject<T>(p_object);
            }
        }
    }
    

    你可以这样称呼它:

    Person jsonClass = JObjects.Get<Person>(stringJson);
    
    string stringJson = JObjects.Get(jsonClass);
    

    PS:

    如果您的json变量名称不是有效的C#名称(名称以 $ 开头),您可以像这样修复:

    public class Exception
    {
       [JsonProperty(PropertyName = "$id")]
       public string id { get; set; }
       public object innerException { get; set; }
       public string message { get; set; }
       public string typeName { get; set; }
       public string typeKey { get; set; }
       public int errorCode { get; set; }
       public int eventId { get; set; }
    }
    

相关问题