[英]How to deserialize JSON string into a C# object?
Consider the following: You have a service which returns a JSON string, and in your C# code you would like to use the returned value as an object (eg: get the various properties of it by their names). 考虑以下几点:您有一个返回JSON字符串的服务,并且在您的C#代码中,您希望将返回值用作对象(例如:通过其名称获取其各种属性)。
Sample JSON: JSON示例:
{
"Name": "Jon Smith",
"Address":
{
"City": "New York",
"State": "NY"
},
"Age": 42
}
Sample C# usage: 示例C#用法:
var object = ... // this is what I am asking for
Console.WriteLine(object.Name); // this should print out "Jon Smith"
Console.WriteLine(object.Address.State); // this should print out "NY"
What options are available in C# without using third party libraries? 在不使用第三方库的情况下 ,C#提供哪些选项?
If you don't know the exact data contract (or you don't care about it), then you can easily do that with the help of System.Web.Helpers.Json
class and a dynamic
object: 如果您不知道确切的数据协定(或者您不关心它),则可以借助
System.Web.Helpers.Json
类和dynamic
对象轻松地做到这一点:
dynamic json = System.Web.Helpers.Json.Decode(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }");
Console.WriteLine(json.Name); // prints "Jon Smith"
Console.WriteLine(json.Address.State); // prints "NY"
A note on that: you will have to add reference to the System.Web.Helpers
assembly. 关于这一点的注释:您将必须添加对
System.Web.Helpers
程序集的引用。
Of course not everyone likes dynamic
, there are some people who prefer to have well defined data contracts. 当然,并不是每个人都喜欢
dynamic
,有些人更喜欢拥有定义明确的数据合同。 For them the solution is a little bit longer: 对于他们来说,解决方案要长一些:
You have to create matching classes for your data contracts, and attribute them accordingly : 您必须为数据合同创建匹配的类,并相应地赋予它们属性 :
// class for the root object:
[DataContract]
public class Person
{
[DataMember]
public string Name { get; set; }
[DataMember]
public Address Address { get; set; }
[DataMember]
public int Age { get; set; }
}
// class for the address object:
[DataContract]
public class Address
{
[DataMember]
public string City { get; set; }
[DataMember]
public string State { get; set; }
}
You can mark members with IgnoreDataMember
attribute to, well, ignore them, or add IsRequired=true
to make them mandatory. 您可以使用
IgnoreDataMember
属性将成员标记为好,或者忽略它们,或者添加IsRequired=true
使它们成为必需的。
After defining those contracts, you can easily parse the JSON string into a Person
object: 定义了这些合同之后,您可以轻松地将JSON字符串解析为
Person
对象:
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Person));
using( MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }")))
{
var person = (Person)ser.ReadObject(stream);
Console.WriteLine(person.Name); // prints "Jon Smith"
Console.WriteLine(person.Address.State); // prints "NY"
}
Note: the DataContractJsonSerializer
resides in the System.ServiceModel.Web
assembly, so you will have to add a reference for that. 注意:
DataContractJsonSerializer
驻留在System.ServiceModel.Web
程序集中,因此您必须为此添加一个引用。 (And of course for the System.Runtime.Serialization
assembly as well.) (当然,还有
System.Runtime.Serialization
程序集。)
To make it easier to use, you can add static Parse
and TryParse
methods to your data contract class: 为了使其更易于使用,可以将静态
Parse
和TryParse
方法添加到数据协定类:
public static Person Parse(string jsonString)
{
if (String.IsNullOrWhiteSpace(jsonString)) throw new ArgumentNullException("The jsonString parameter shouldn't be null or an empty string.");
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Person));
using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)))
{
return (Person)ser.ReadObject(stream);
}
}
public static bool TryParse(string jsonString, out Person result)
{
try
{
result = Person.Parse(jsonString);
return true;
}
catch (Exception ex)
{
if (ex is ArgumentNullException || ex is SerializationException)
{
result = null;
return false;
}
throw;
}
}
As LB mentioned in their comment, you can use JavaScriptSerializer
- if you add a reference to the System.Web.Extensions
assembly - to make it even simpler: 正如LB在他们的评论中提到的那样,如果添加对
System.Web.Extensions
程序集的引用,则可以使用JavaScriptSerializer
使其更简单:
var person = new JavaScriptSerializer().Deserialize<Person>(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }");
For that you still need the classes from above, but you can leave out the - "ugly" - attributes if you would like to. 为此,您仍然需要上面的类,但是如果愿意,可以省略-“ ugly”-属性。 (But with this method you lose the ability to mark parts as mandatory...)
(但是使用这种方法,您将无法将零件标记为强制性...)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.