【问题标题】:Deserialize JSON into C# dynamic object?将 JSON 反序列化为 C# 动态对象?
【发布时间】:2011-03-09 17:18:52
【问题描述】:

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

【问题讨论】:

  • 如果你想要一些“动态”的东西,为什么不直接使用大多数 JSON 解码器附带的 get-style 访问器呢? (例如,真的需要“动态”对象创建吗?)json.org 有一堆 C# JSON 实现的链接。
  • 我正在开展一个项目,该项目试图将外部依赖关系降至最低。因此,如果可以使用股票 .net 序列化程序和首选类型。当然,如果不可能,我会访问 json.org。谢谢!
  • 我真的很惊讶 C# 团队添加了“动态”,但是 CLR 中没有办法将 JSON 对象转换为动态 CLR 类实例。
  • 不幸的是,接受的答案在 .NET 4 RTM 中不起作用。我发布了一个答案,帮助我着手解决这个问题,这可能对其他人有用。
  • 2018 年 10 月更新,这就是神奇的发生方式:stackoverflow.com/a/48023576/4180382

标签: c# .net json serialization dynamic


【解决方案1】:

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

dynamic data = Json.Decode(json);

它包含在 MVC 框架中,作为 .NET 4 框架的 additional download。如果有帮助,请务必给 Vlad 一个赞成票!但是,如果您不能假设客户端环境包含此 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)

【讨论】:

  • 动态 obj = serializer.Deserialize(json, typeof(object));说具有 2 个参数的方法没有重载..错误的 dll 还是什么?
  • 我发现你的 ToString 方法对我不起作用,所以我重写了它。它可能有一些错误,但它正在处理我的数据集,所以我会在这里为其他可能遇到问题的人提供它:pastebin.com/BiRmQZdz
  • 您可以使用 System.Web.Helpers.Json - 它提供了一个返回动态对象的 Decode 方法。我也发布了此信息作为答案。
  • 有时在 js 中你有一些特殊字符的字段,比如“背景颜色”。要访问 js 中的此类字段,请执行 obj["background-color"]。反序列化为动态对象后,如何从 c# 访问这些字段?当然,我不能做 obj.background-color,而且 obj["background-color"] 似乎不起作用。如果动态对象也可以同时作为字典访问就好了,就像在 js 中一样。
  • @RaduSimionescu 我可能有点晚了,但这可能对未来的访客有所帮助。我遇到了同样的问题,只是字段名称 params (这是 C# 中的关键字)。除了TryGetMember 之外,您还可以覆盖TryGetIndex,它提供与JS 中完全相同的行为。然后你可以使用obj["params"]obj["background-color"] 来获取尴尬的字段名称。
【解决方案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

【讨论】:

  • @HotLicks:要反省动态 stuff,请执行以下操作:foreach (Newtonsoft.Json.Linq.JProperty jproperty in stuff) { Console.WriteLine("jproperty.Name = {0}", jproperty.Name);}
  • JsonConvert.DeserializeObject 和 JObject.Parse 有什么区别?答案是以相同的方式使用它们来做同样的事情,但没有解释差异。
  • @TomPeplow 试过这个。它对我不起作用。它说“JObject 没有实现 'Name'”。
  • 我无法让它工作。我已将问题缩小到async 方法内。如果我使方法同步,它会按预期工作。但是,使方法async无法得到dynamic,我只得到object。显式转换什么都不做,仍然只是给我一个object。有没有其他人遇到过这种情况?
【解决方案3】:

您可以使用System.Web.Helpers.Json 执行此操作 - 它的 Decode 方法返回一个动态对象,您可以随意遍历该对象。

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

var dynamicObject = Json.Decode(jsonString);

【讨论】:

  • 仅供参考 System.Web.Helpers.dll 需要 .net 4.0 但不包含在 .net 4.0 中。它可以与 ASP.NET MVC 3 一起安装
  • 您将在 Visual Studio 2012 的程序集下的扩展组中找到此程序集
  • 使用动态有什么问题吗?如果输入 JSON 不包含属性,我们如何有效处理异常..
  • 如果您想要强类型化模型,请务必使用 Json.Decode(string) 方法。
  • 将此库添加到您的项目中:stackoverflow.com/questions/8037895/…
【解决方案4】:

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

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

这是最简单的方法。

【讨论】:

  • 你试过了吗?它返回Dictionary&lt;string,object&gt;。除非我遗漏了什么,否则您的示例不会返回动态对象。
  • 这不行,它只是以动态的形式返回一个dict
  • @Peter Long 我相信我没有清楚地说明我的情况,亲爱的。让我尝试纠正我的错误。我知道什么是动态。这不允许您传入 JSON 对象并使用 d.code,您必须执行 d["code"].Value,这不是大多数找到此答案的人想要的,我们已经知道如何获取字典并将其转换为动态完全是浪费时间。我不同意,先生。
  • @mattmanser,we already know how to get the dictionary and casting it to a dynamic。它不一定是字典。除了字典之外,Json 也有列表。列表和字典也可以嵌套。我的代码可以处理所有这些情况。但是你的方法不行。
  • @mattmanser 是对的;可以实现IDynamicMetaObjectProvider(或使用例如ExpandoObject),它能够拦截属性并在内部字典中查找它们。这与dynamic 的使用相结合,允许使用诸如d.code 之类的代码。将字典转换为动态是毫无意义的。
【解决方案5】:

没有任何第三方 DLL 文件的简单“字符串 JSON 数据”对象:

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);

【讨论】:

  • 我不明白。这是迄今为止最简单的解决方案,没有人提及。
  • 是的,很简单 :) 有时您需要序列化但不想包含第三部分 dll
  • 您能否详细说明:动态如何通过myObject["myprop"] 访问反序列化对象?我知道它是在运行时完成的,但是如何通过myObject["myprop"] 访问它是有效的?
  • 你可以像 Personel item = serializer.Deserialize(getString); 那样反序列化你的对象。如果你使用动态对象,你也可以使用数组,一切皆有可能,就像everyobject
  • 要使用 System.Web.Script.Serialization 命名空间,您的项目需要引用 System.Web.Extensions。
【解决方案6】:

您可以在 Newtonsoft.Json 的帮助下实现这一目标。从 NuGet 安装它,然后:

using Newtonsoft.Json;

dynamic results = JsonConvert.DeserializeObject<dynamic>(YOUR_JSON);

【讨论】:

    【解决方案7】:

    JsonFx 可以将 JSON 内容反序列化为动态对象。

    序列化到/从动态类型(.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]}
    

    【讨论】:

      【解决方案8】:

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

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

      【讨论】:

        【解决方案9】:

        我制作了一个使用 Expando 对象的 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) })); }
                }
            }
        }
        

        【讨论】:

          【解决方案10】:

          Newtonsoft.Json 创建动态对象真的很棒。

          //json is your string containing the JSON value
          dynamic data = JsonConvert.DeserializeObject<dynamic>(json);
          

          现在您可以像访问常规对象一样访问data 对象。这是我们目前作为示例的 JSON 对象:

          { "ID":123,"Name":"Jack","Numbers":[1, 2, 3] }
          

          这是反序列化后的访问方式:

          data.ID //Retrieve the int
          data.Name //Retrieve the string
          data.Numbers[0] //Retrieve the first element in the array
          

          【讨论】:

            【解决方案11】:

            我使用http://json2csharp.com/ 来获取代表 JSON 对象的类。

            输入:

            {
               "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; }
            }
            

            【讨论】:

              【解决方案12】:

              最简单的方法是:

              只需包含此DLL file

              使用如下代码:

              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.
              

              【讨论】:

                【解决方案13】:

                另一种选择是“将 JSON 粘贴为类”,这样可以快速轻松地对其进行反序列化。

                1. 只需复制整个 JSON
                2. 在 Visual Studio 中:单击编辑选择性粘贴将 JSON 粘贴为类

                这里有一个更好的解释 n piccas... ‘Paste JSON As Classes’ in ASP.NET and Web Tools 2012.2 RC

                【讨论】:

                • 这为我节省了很多时间!应该被选为最佳答案!
                【解决方案14】:

                您可以扩展 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 中定义它们......另一个技巧是不使用命名空间,那么你就不用完全需要 using 语句),您可以像这样使用它们:

                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
                

                【讨论】:

                  【解决方案15】:

                  您可以使用using Newtonsoft.Json

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

                  resolvedEvent.Event.Data 是我从调用 core Event 得到的响应。

                  【讨论】:

                    【解决方案16】:

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

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

                    【讨论】:

                    • 但这不是问题要问的。当您必须为每个 json 字符串指定类型并使用动态类型时,情况会有所不同。
                    【解决方案17】:

                    看看我在 CodeProject 上写的那篇文章,正好回答了这个问题:

                    Dynamic types with JSON.NET

                    在这里重新发布它太多了,而且更没有意义,因为该文章有一个带有密钥/所需源文件的附件。

                    【讨论】:

                      【解决方案18】:

                      试试这个:

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

                      【讨论】:

                      • 到目前为止我最喜欢的方法
                      • 老兄,为你 +1 拥抱:D
                      【解决方案19】:

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

                      【讨论】:

                      • 一个例子将帮助更广泛的受众
                      • 我不明白为什么这个答案高于 700 多票并被标记为正确答案的答案!?
                      • @Vidar 您是按最旧而不是按投票排序吗?
                      【解决方案20】:

                      获取 ExpandoObject:

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

                      【讨论】:

                        【解决方案21】:

                        使用包含在该库中的 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

                        【讨论】:

                        • 这种方法允许“遍历”json文档,这样您就可以管理JSON结构未知或可变的情况(例如,许多API在发生错误时返回完全不同的JSON文档) .除了 Newtonsoft.JSON(又名 JSON.NET)之外,还有其他库允许这样做吗?
                        【解决方案22】:

                        您想要的对象 DynamicJSONObject 包含在来自 ASP.NET 网页包的 System.Web.Helpers.dll 中,它是 WebMatrix 的一部分。

                        【讨论】:

                          【解决方案23】:

                          有一个用于 C# 的轻量级 JSON 库,名为 SimpleJson

                          它支持 .NET 3.5+、Silverlight 和 Windows Phone 7。

                          它支持 .NET 4.0 的动态

                          它也可以作为 NuGet 包安装

                          Install-Package SimpleJson
                          

                          【讨论】:

                          【解决方案24】:

                          在 JavaScript 中使用 DataSet(C#)。一个使用 DataSet 输入创建 JSON 流的简单函数。创建 JSON 内容,例如(多表数据集):

                          [[{a:1,b:2,c:3},{a:3,b:5,c:6}],[{a:23,b:45,c:35},{a: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},{a:58,b:59,c:45}]]')
                          

                          然后使用:

                          d[0][0].a // out 1 from table 0 row 0
                          
                          d[1][1].b // out 59 from table 1 row 1
                          
                          // Created 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;
                          }
                          

                          【讨论】:

                            【解决方案25】:

                            如何使用动态和 JavaScriptSerializer 解析简单的 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();
                            }
                            

                            【讨论】:

                              【解决方案26】:

                              我想在单元测试中以编程方式执行此操作,我确实可以输入它。

                              我的解决办法是:

                              var dict = JsonConvert.DeserializeObject<ExpandoObject>(json) as IDictionary<string, object>;
                              

                              现在我可以断言了

                              dict.ContainsKey("ExpectedProperty");
                              

                              【讨论】:

                                【解决方案27】:

                                我来这里是为了寻找 .NET Core 的答案,没有任何第三方或其他参考。如果您将ExpandoObject 与标准JsonSerializer 类一起使用,它可以正常工作。这是对我有用的示例:

                                using System.Text.Json;
                                using System.Dynamic;
                                
                                dynamic json = JsonSerializer.Deserialize<ExpandoObject>(jsonText);
                                Console.WriteLine(json.name);
                                

                                此代码打印出传递给Deserialize 方法的 JSON 文本中存在的名称属性的字符串值。瞧——没有额外的库,什么都没有。只是 .NET 核心。

                                编辑:嵌套元素的多个级别的 json 可能存在问题。适用于单层平面对象。

                                【讨论】:

                                • 它在 .net 6 中不起作用,知道吗?我想读取具有元素数组的属性。
                                • 它只适用于原始类型属性,因为 expando 对象处理按名称读取的属性并按原样返回值。问题是 Console.WriteLine 通过调用 ToString 将值转换为字符串,这对于原始类型将给出正确的值。对于数组,您可能在输出中看到的不是实际值而是对象类型。
                                【解决方案28】:

                                使用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("$..key1")
                                    )
                                {
                                    foreach (var rec in p)
                                    {
                                        Console.WriteLine("Action: " + rec.action);
                                        Console.WriteLine("Timestamp: " + rec.timestamp);
                                        Console.WriteLine("URL: " + rec.url);
                                        Console.WriteLine("IP address: " + rec.ip);
                                    }
                                }
                                

                                输出:

                                Action: open
                                Timestamp: 2018-09-05 20:46:00
                                URL: http://www.google.com
                                IP address: 66.102.6.98
                                

                                小提琴样例:https://dotnetfiddle.net/S0ehSV

                                更多信息,请访问codeproject文章

                                免责声明:我是这个库的作者。

                                【讨论】:

                                  【解决方案29】:

                                  试试这个方法!

                                  JSON 示例:

                                  [{
                                      "id": 140,
                                      "group": 1,
                                      "text": "xxx",
                                      "creation_date": 123456,
                                      "created_by": "xxx@gmail.co",
                                      "tags": ["xxxxx"]
                                    }, {
                                      "id": 141,
                                      "group": 1,
                                      "text": "xxxx",
                                      "creation_date": 123456,
                                      "created_by": "xxx@gmail.com",
                                      "tags": ["xxxxx"]
                                  }]
                                  

                                  C#代码:

                                  var jsonString = (File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(),"delete_result.json")));
                                  var objects = JsonConvert.DeserializeObject<dynamic>(jsonString);
                                  foreach(var o in objects)
                                  {
                                      Console.WriteLine($"{o.id.ToString()}");
                                  }
                                  

                                  【讨论】:

                                    【解决方案30】:

                                    如果您想在反序列化 JSON 时跳过创建类,可以使用 NewtonSoft.JsonDeserializeAnonymousType 方法来完成。

                                    以下示例甚至可以将 JSON 反序列化为匿名对象的列表

                                    var json = System.IO.File.ReadAllText(@"C:\TestJSONFiles\yourJSONFile.json");
                                    var fooDefinition = new { a = "", b = 0 }; // type with fields of string, int
                                    var fooListDefinition = Enumerable.Range(0, 0).Select(e => fooDefinition).ToList();
                                    
                                    var foos = JsonConvert.DeserializeAnonymousType(json, fooListDefinition);
                                    

                                    【讨论】:

                                      猜你喜欢
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2022-01-21
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2015-08-05
                                      • 1970-01-01
                                      • 1970-01-01
                                      相关资源
                                      最近更新 更多