关于.NET:将JSON反序列化为C#动态对象?

Deserialize JSON into C# dynamic object?

是否有方法将JSON内容反序列化为C 4动态类型?为了使用DataContractJSonserializer,最好跳过创建一组类。

  • 如果您想要"动态"的东西,为什么不使用大多数JSON解码器附带的get-style访问器,而不使用普通的旧对象呢?(例如,是否确实需要"动态"对象创建?)json.org有一系列用于c json实现的链接。
  • 我正在做一个项目,它试图将外部依赖性降到最低。所以,如果有可能使用stock.net序列化程序和类型,那就更好了。当然,如果不可能的话,我会去json.org。谢谢!
  • 我真的很惊讶C团队添加了"dynamic",但是在clr中没有办法将JSON对象转换为动态clr类实例。
  • 不幸的是,接受的答案在.NET 4 RTM中不起作用。我贴出了一个答案,帮助我完成这项工作,这可能对其他人有用。
  • (尽管看起来newtonsoft json.net非常接近。不过,没有任何真正好的例子。)
  • 更新2018年10月,魔法就是这样发生的:stackoverflow.com/a/48023576/4180382


如果您愿意依赖System.Web.Helpers组件,则可以使用Json类:

1
dynamic data = Json.Decode(json);

它包含在MVC框架中,作为对.NET 4框架的附加下载。如果有帮助的话,一定要给vlad一个赞成票!但是,如果您不能假定客户机环境包含此dll,则继续阅读。

这里建议使用另一种反序列化方法。我稍微修改了代码以修复bug并适应我的编码风格。您所需要的只是这个代码和项目中对System.Web.Extensions的引用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
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
}

您可以这样使用它:

1
2
3
4
5
6
string json = ...;

var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new DynamicJsonConverter() });

dynamic obj = serializer.Deserialize(json, typeof(object));

因此,给定一个JSON字符串:

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

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

1
2
3
4
5
6
7
8
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)

  • 感谢Drew,您的TryGetMember将我的问题分类为递归到嵌套集合中,但您是否可以让我们知道是什么使它起作用。数组列表是否被强制转换为IDictionary,然后被投影为dynamicjsonObjects,而不是被投影为arraylist成员?希望这不是一个太愚蠢的问题。谢谢你的回答:)
  • @马克,我看这个已经有一段时间了,但从记忆中你所描述的听起来是对的。
  • 我在dynamic obj=serializer.deserialize(json,typeof(object))中得到一个错误;说带有2个参数的方法没有重载..错误的dll或什么?
  • @Stewie,我使用的类型是System.Web.Script.Serialization.JavaScriptSerializer,它在System.Web.dll的4.0.0.0版本中。
  • system.web.script.serialization.javascriptserializer位于system.web.extensions.dll-goo.gl/8zrrj中
  • @拉什内洛,你说得对。
  • 我发现你的扭结方法对我不起作用,所以我重写了它。它可能有一些bug,但它正在处理我的数据集,所以我将在这里为可能遇到此问题的任何其他人提供它:pastebin.com/birmqzdz
  • 这在vb.net中可行吗?
  • @蒂姆,我不明白为什么,但我对vb.net还不够熟悉,无法为您转换代码。您可以编译C代码并通过程序集引用使用它,或者尝试自己转换它。我不认为这太难转变。
  • 是的,我已经使用了C组件,但它仍然是相同的。这种"动态"的目标检测不起作用。在我的例子中,"数据"是一个对象数组,每个对象都包含JSON数据的键值对。
  • 您可以使用system.web.helpers.json——它提供了一个解码方法,返回一个动态对象。我也发布了这个信息作为答案。
  • 无法分析此字符串:(不确定是否可以访问此字符串)dropbox.com/s/aefohe97t3aq81y/json-data.txt
  • 这也帮了我很大的忙,但是我很好奇如果我需要使用.serialize方法,我应该怎么做,它目前只抛出NotImplementedException…我不太熟悉密封类和/或扩展抽象类。有人能给我指出正确的方向吗?
  • 在JS中,有时会有一些带有特殊字符的字段,比如"背景色"。要访问JS中的此类字段,请执行obj["background color"]。在反序列化到动态对象之后,如何从C访问这些字段?当然,我不能使用背景色,而obj[背景色]似乎不起作用。如果动态对象也可以像在JS中一样以字典的形式访问,那就太好了。
  • @Radusimionescu,你试过用连字符替换下划线吗?我自己也没试过,但我记得这件事。
  • @谢谢你的课。你能在答案中指定"动态视图"不适用于你的类吗?对我来说,这是一种意想不到的行为——起初我以为你们班根本不起作用。
  • @探索者,我不确定你所说的"动态视图"到底是什么意思。
  • @Radusimionescu我可能晚了一点,但这可能会帮助未来的游客。我也遇到了同样的问题,只是字段名params(这是c中的关键字)。除了TryGetMember之外,您还可以覆盖TryGetIndex,这与JS中的行为完全相同。然后,您可以对笨拙的字段名执行obj["params"]obj["background-color"]
  • @M.Buettner,我自己也没试过,但是你可以用一个@字符作为前缀来解决C中的一些关键字冲突。例如,以下是有效的c:string @class ="MyClass";
  • @德伦奥克斯,嗯,很好知道-我可能会在我的情况下使用它。但我想这并不能解决连字符的问题。
  • 不会在MVC 5上工作,见汤姆·佩普洛的回答。
  • system.web.helpers可以在vs2015中使用package manage console通过以下命令下载:install package system-web-helpers.dll also,system.web.mvc中的json与system.web.helpers中的json冲突。所以您可以使用dynamic data=system.web.helpers.json.decode(myjsonString);
  • 是否有与此相关的成本,而不是使用单个类?
  • 从何处获取system.web.helpers dll?你所指的那篇文章没有反问的意思。
  • @Melbournedeveloper来看看stackoverflow.com/q/8037895/24874
  • 我已经看过了。没有答案。德雷诺克斯
  • 仅供参考,如果您使用的是.NET核心,他们会将此内容移动到"Microsoft Web助手"包中。
  • 要使用system.web.helpers,需要添加nuget包:nuget.org/packages/microsoft-web-helpers


使用json.net非常简单:

1
2
3
4
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

1
2
3
4
dynamic stuff = JObject.Parse("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

string name = stuff.Name;
string address = stuff.Address.City;

文档:使用动态查询JSON

  • 有趣的是,使用MVC,如何将其绑定到视图?我阅读了一些关于动态或匿名类型绑定的文章,但没有看到如何使用它的示例。假设我有可能有很多层的JSON。
  • 如何反省动态stuff
  • @热点:反省动态的stuff做一些像:foreach (Newtonsoft.Json.Linq.JProperty jproperty in stuff) { Console.WriteLine("jproperty.Name = {0}", jproperty.Name);}的事情。
  • jsonConvert.DeserializeObject和jobject.Parse有什么区别?答案是以同样的方式使用它们来做同样的事情,但不能解释两者之间的区别。
  • @汤普洛试过这个。它对我不起作用。它说"jobject不实现‘name’"。
  • @cja没有区别:stackoverflow.com/questions/23645034/&hellip;
  • 我不能让这个工作。我把问题缩小到了使用async方法的范围内。如果使方法同步,它将按预期工作。但是,做方法async,我不能得到dynamic,我只能得到object。显式铸造什么也没有,只是给了我一个object。其他人也经历过吗?
  • 我是说,对性能有什么副作用吗?正如我看到的,json.net声称它比其他的两个newtonsoft.com/json快,但是当我们使用动态对象时…性能会保持不变吗?
  • 不明白我做错了什么。在Mono环境中,动态对象没有反序列化,它是相同的,但是如果传递特定的类型,它将反序列化。我错过了什么?
  • @共同讨论有问题的人可能缺少对Microsoft.CSharp的引用?dynamic需要这个引用(async也需要这个引用--在这里我可能错了)
  • 牛顿索夫特编辑了这个问题。很酷。
  • 我会使用Newtonsoft JSON,但是文档非常差。例子不多。我需要知道如何处理数组,如何将子对象作为属性来处理,如何检查属性是否存在,如何将JSON值类型(整数、小数、布尔值、空值)转换为C…一个简单的样本就足够了,但看起来我正在寻找最奇怪的东西。


您可以使用system.web.helpers.json来实现这一点——它的decode方法返回一个动态对象,您可以根据需要遍历该对象。

它包含在system.web.helpers程序集(.net 4.0)中。

1
var dynamicObject = Json.Decode(jsonString);

  • fyi 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/&hellip;


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

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

这是最简单的方法。

  • 以前的大多数答案都在.NET 4.0 RTM之前。
  • 你试过这个吗?返回Dictionary。除非我遗漏了一些东西,否则您的示例不会返回动态对象。
  • @塞吉奥佩雷拉是的,是的。可以将任何类型强制转换为动态类型。那为什么不做个演员呢?
  • 这不起作用,它只是以动态的形式返回一个dict
  • @马特曼,请学习什么是动态的。最后,每个动态类型都将解析为静态类型。
  • @彼得·朗,我相信我没有清楚地陈述我的情况,亲爱的家伙。让我试着改正我的错误。我知道什么是动力。这不允许您传入JSON对象并使用d.code,您必须执行d["code"].value,这不是大多数找到此答案的人想要的,我们已经知道如何获取字典并将其转换为动态的,这完全是在浪费时间。我恭敬地不同意,先生。
  • @Mattmanser…我已经浪费了那些时间尝试他的代码,因为我没有阅读评论或向下滚动:(
  • @马特曼,我真的不理解你。我的答案被选为最佳答案。请想想谁错了。
  • @Mattmanser,we already know how to get the dictionary and casting it to a dynamic。它不一定是一种措辞。JSON除了字典还有列表。列表和字典也可以嵌套。我的代码可以处理所有这些情况。但你的方法不行。
  • @Mattmanser,你要的不是d["code"].Value,而是d.code。据我所知,这是不可能的(或毫无意义的)。将动态视为将编译器作业的一部分延迟到运行时。这就是动态的有用之处。动态不是解决问题的手段。
  • @Mattmanser在绊倒-这很好-谢谢Peter+1
  • 谢谢你,彼得,这正是我需要的!
  • 这是一个简单而直接的答案…**而且它是有效的**。虽然有些第三方库功能更全面、效率更高(我们会想到ServiceStack,而不是那些被高估和过度膨胀的json.net库),但有时如果您不需要速度,最好使用本机选项(从.NET 4.x开始提供),而且@mattmanser在所有方面都是错误的;他没有EEM要掌握他发表评论时的动态类型。
  • @Mattmanser是对的;它可以实现能够拦截属性并在内部字典中查找它们的IDynamicMetaObjectProvider(或使用,例如ExpandoObject)。结合使用dynamic允许使用诸如d.code之类的代码。把字典强制转换成动态字典是毫无意义的。
  • 我反对这个答案,尽管这个答案并没有严格返回一个IDynamicMetaObjectProvider对象。我的意思是,它对那些完全不希望它充满活力的人很有用。OP声明他希望避免创建自定义类和属性,这个答案很有帮助。不过,彼得朗的回答本可以更清楚地说明这一点。我可以编辑这个答案吗?
  • @彼得龙+1谢谢
  • 上面的讨论是"dynamic"变量声明(@peterlong's topic)和"dynamicObject"类型(@mattmanser's desired result)之间混淆的结果。有关这两者的详细信息,请参阅文档(一如既往):docs.microsoft.com/en-us/dotnet/csharp/programming guide/typ&zwnj;&误8203;es/&hellip;docs.microsoft.com/en-us/dotnet/csharp/programming guide/typ&zwnj;&误8203;es/&hellip;


简单的"string json data"到不带任何第三方dll文件的对象:

1
2
3
4
5
6
7
8
9
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

注意:您也可以使用自定义对象。

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

  • 我不明白。这是迄今为止最简单的解决方案,没有人提及。
  • 是的,很简单:)有时您需要序列化,但不想包括第三部分DLL
  • 您能否详细说明:如何通过:myObject["myprop"]动态访问反序列化对象?我知道它是在运行时完成的,但是如何通过myObject["myprop"]访问它是有效的?
  • 您可以对对象进行反序列化,如personalitem=serializer.deserialize(getstring);如果您使用动态对象,也可以使用数组,并且所有操作都可以像everyObject一样进行。
  • 要使用system.web.script.serialization命名空间,项目需要引用system.web.extensions。


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

Serialize to/from dynamic types (default for .NET 4.0):

1
2
3
4
5
6
7
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]}

我制作了一个使用Expando对象的动态JSonConverter的新版本。我使用expando对象,因为我想使用json.net将动态序列化回json。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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) })); }
        }
    }
}

使用newtonsoft.json的另一种方法:

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

最简单的方法是:

只包括这个dll文件。

使用如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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.


您可以扩展javascriptserializer以递归地复制它创建的字典以扩展对象,然后动态地使用它们:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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语句),您可以这样使用它们:

1
2
3
4
5
6
7
8
9
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

您可以使用using Newtonsoft.Json

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

resolvedEvent.Event.Data是我从呼叫核心事件得到的响应。


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

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

  • 但这不是问题所在。当您必须为每个JSON字符串指定类型并使用动态类型时,情况就不同了。


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


看看我在codeproject上写的文章,它精确地回答了这个问题:

带有json.net的动态类型

在这里重新发布的内容太多了,甚至更少,因为该文章有一个带有键/必需源文件的附件。


我使用http://json2charp.com/获取表示JSON对象的类。

输入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
  "name":"John",
  "age":31,
  "city":"New York",
  "Childs":[
      {
        "name":"Jim",
        "age":11
      },
      {
        "name":"Tim",
        "age":9
      }
   ]
}

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
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来填充这个类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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);
        }
    }
}

你可以这样称呼它:

1
2
3
Person jsonClass = JObjects.Get<Person>(stringJson);

string stringJson = JObjects.Get(jsonClass);

PS:

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

1
2
3
4
5
6
7
8
9
10
11
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; }
}

试试这个:

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

json.net中的反序列化可以使用该库中包含的JObject类实现动态。我的JSON字符串代表这些类:

1
2
3
4
5
6
7
8
public class Foo {
   public int Age {get;set;}
   public Bar Bar {get;set;}
}

public class Bar {
   public DateTime BDay {get;set;}
}

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

1
2
3
4
5
6
7
8
9
10
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());

或者如果你想更深入:

1
2
3
4
5
6
7
8
9
10
11
12
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了解完整的示例。


将数据集(c)与JavaScript一起使用。用于创建带有数据集输入的JSON流的简单函数。创建JSON内容,如(多表数据集):

1
[[{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。例如,

1
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}]]')

然后使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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 +=
<hr><P>有一个轻量级的C JSON库,称为simpleJSON。</P><P>它支持.NET 3.5+、Silverlight和Windows Phone 7</P><P>它支持.NET 4.0的动态</P><P>它也可以作为nuget包安装</P>[cc lang="csharp"]Install-Package SimpleJson


希望使用dynamicjsonObject的对象包含在ASP.NET网页包的system.web.helpers.dll中,该包是WebMatrix的一部分。


To get an ExpandoObject:

1
2
3
4
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

Container container = JsonConvert.Deserialize<Container>(jsonAsString, new ExpandoObjectConverter());

如何使用动态javascriptserializer解析简单的JSON内容

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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();
}

另一个选项是"将JSON粘贴为类",以便快速轻松地反序列化它。

  • 只需复制整个JSON
  • 在Visual Studio中:单击"编辑"&rarr;"选择性粘贴"&rarr;"将JSON粘贴为类"
  • 这是一个更好的解释。在ASP.NET和Web工具2012.2 rc中"将JSON粘贴为类"


    使用Cinchoo ETL——一个可用于将JSON解析为动态对象的开放源代码库:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    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 address:" + rec.ip);
        }
    }

    输出:

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

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