使用Json.net将JSON对象反序列化为动态对象


426

是否可以使用json.net从json反序列化返回动态对象?我想做这样的事情:

dynamic jsonResponse = JsonConvert.Deserialize(json);
Console.WriteLine(jsonResponse.message);

1
考虑从JSON json2csharp.com生成C#类,并使用生成的类而不是动态类
Michael Freidgeim


您如何建议stackOverflow将问题“太旧”关闭?至今已有六年了,从那时起,每个版本的.net都有有效的答案和合理的建议。。。
安德鲁·洛里安(Andrew lorien)'17

Answers:


546

Json.NET允许我们执行以下操作:

dynamic d = JObject.Parse("{number:1000, str:'string', array: [1,2,3,4,5,6]}");

Console.WriteLine(d.number);
Console.WriteLine(d.str);
Console.WriteLine(d.array.Count);

输出:

 1000
 string
 6

此处的文档:使用Json.NET的LINQ to JSON

另请参见JObject.ParseJArray.Parse


36
请注意,对于数组,语法为JArray.Parse
jgillich 2014年

4
为什么我们需要使用动态词?我很害怕以前从未使用过:D
MonsterMMORPG,2014年

3
在VB.Net中,您需要做Dim d As Object = JObject.Parse("{number:1000, str:'string', array: [1,2,3,4,5,6]}")
ilans 2014年

2
@MonsterMMORPG您应该是:)几乎在每种情况下,动态模式都是一种反模式,但是有时您可能会遇到合理使用它的情况。
Pluc

4
对于Newtonsoft.Json 8.0.3(.NET 4.5.2):发生Microsoft.CSharp.RuntimeBinder.RuntimeBinderException HResult = -2146233088消息='Newtonsoft.Json.Linq.JObject'不包含对'number'的定义Source = Microsoft .CSharp StackTrace:在Microsoft.CSharp.RuntimeBinder.RuntimeBinderController.SubmitError(CError pError)
user4698855 '16

107

从Json.NET 4.0 Release 1开始,提供了本机动态支持:

[Test]
public void DynamicDeserialization()
{
    dynamic jsonResponse = JsonConvert.DeserializeObject("{\"message\":\"Hi\"}");
    jsonResponse.Works = true;
    Console.WriteLine(jsonResponse.message); // Hi
    Console.WriteLine(jsonResponse.Works); // True
    Console.WriteLine(JsonConvert.SerializeObject(jsonResponse)); // {"message":"Hi","Works":true}
    Assert.That(jsonResponse, Is.InstanceOf<dynamic>());
    Assert.That(jsonResponse, Is.TypeOf<JObject>());
}

而且,当然,获取当前版本的最佳方法是通过NuGet。

已于2014年11月12日更新以解决评论:

这工作得很好。如果在调试器中检查类型,则实际上该值是动态的。所述底层的类型是一个JObject。如果您想控制类型(例如指定ExpandoObject,则可以这样做)。

在此处输入图片说明


20
这似乎从来没有奏效。它仅返回JObject,而不返回动态变量。
保罗

12
顺便说一句,这有效:JsonConvert.DeserializeObject <ExpandoObject>(STRING); 与适当的反序列化,因此我们没有JObject等
。– Gutek

2
@Gutek不知道您的问题是什么。您运行代码了吗?我在测试中添加了断言,并在原始json中添加了一个属性。包括调试器的屏幕截图。
David Peden 2014年

1
@DavidPeden如果您拥有JObject,并且尝试在Razor中将其绑定,则将获得异常。问题是关于反序列化为动态对象-JObject是动态的,但包含“自己的”类型,例如JValue而不是原始类型。@Model.Prop如果返回类型为JValue,则无法在Razor中使用name。
Gutek

2
这可行,但是每个动态属性都是一个JValue。这让我感到困惑,因为我在调试器/立即窗口中工作,而不仅仅是看到strings。David在底部屏幕截图中显示了这一点。它JValue是可转换的,所以您可以做string m = jsonResponse.message
卢克·普普利特

66

如果只是反序列化为动态,则将获得JObject。您可以使用ExpandoObject获得所需的内容。

var converter = new ExpandoObjectConverter();    
dynamic message = JsonConvert.DeserializeObject<ExpandoObject>(jsonString, converter);

1
结果也可以转换为字典
FindOutIslamNow18

1
正是我要找的东西!谢谢!
DarkDeny

42

我知道这是旧文章,但JsonConvert实际上有不同的方法,因此

var product = new { Name = "", Price = 0 };
var jsonResponse = JsonConvert.DeserializeAnonymousType(json, product);

23
那将把json负载反序列化为匿名类型,而不是动态类型。匿名类型和动态类型是不同的东西,我认为这不能解决所提出的问题。
jrista

1
是否需要使用两个变量?为什么不重用第二个语句中的第一个?
RenniePet

21

是的,您可以使用JsonConvert.DeserializeObject做到这一点。为此,只需执行以下操作:

dynamic jsonResponse = JsonConvert.DeserializeObject(json);
Console.WriteLine(jsonResponse["message"]);

1
JsonConvert不包含称为的方法Deserialize
CanPoyrazoğlu2015年

它应该只是DeserializeObject,但这应该是IMO接受的答案
superjugy

21

注意:在2010年我回答这个问题时,没有某种类型就无法进行反序列化,这使您无需定义实际的类即可进行反序列化,并允许使用匿名类进行反序列化。


您需要某种反序列化的类型。您可以按照以下方式进行操作:

var product = new { Name = "", Price = 0 };
dynamic jsonResponse = JsonConvert.Deserialize(json, product.GetType());

我的答案基于.NET 4.0在JSON序列化器中构建的解决方案。反序列化为匿名类型的链接在这里:

http://blogs.msdn.com/b/alexghi/archive/2008/12/22/using-anonymous-types-to-deserialize-json-data.aspx


我和你在一起,菲尔不知道为什么人们不赞成这个,如果有人可以请..请解释为什么?
PEO

18
他们之所以投票,是因为问题在于没有类型的反序列化。
理查德

4
在没有其他解决方案的情况下,答案在2010年撰写时是有效的。甚至在很短的一段时间内,这都是公认的答案,直到JSON.NET支持。
2017年

1
这不会产生动态对象。这将生成一个JObject,您将其作为动态引用。但是它里面还是一个JObject。
ghostbust555

5

如果您将JSON.NET与不是JObject的旧版本一起使用。

这是从JSON创建动态对象的另一种简单方法:https : //github.com/chsword/jdynamic

NuGet安装

PM> Install-Package JDynamic

支持使用字符串索引访问成员,例如:

dynamic json = new JDynamic("{a:{a:1}}");
Assert.AreEqual(1, json["a"]["a"]);

测试用例

您可以按以下方式使用此实用程序:

直接获取价值

dynamic json = new JDynamic("1");

//json.Value

2,在json对象中获取成员

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 integer: 1

3.IEnumerable

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.

其他

dynamic json = new JDynamic("{a:{a:1} }");

//json.a.a is 1.

2

是的,有可能。我一直都在这样做。

dynamic Obj = JsonConvert.DeserializeObject(<your json string>);

对于非本地类型,这有点棘手。假设在Obj内部,有一个ClassA和ClassB对象。它们都转换为JObject。您需要做的是:

ClassA ObjA = Obj.ObjA.ToObject<ClassA>();
ClassB ObjB = Obj.ObjB.ToObject<ClassB>();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.