考虑以下内容:您有一个返回JSON字符串的服务,并且在您的C#代码中,您希望将返回值用作对象(例如:通过其名称获取其各种属性)。
样本JSON:
{ "Name": "Jon Smith", "Address": { "City": "New York", "State": "NY" }, "Age": 42 }
示例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"
在不使用第三方库的情况下,C#提供哪些选项?
如果您不知道确切的数据协定(或您不关心它),则可以借助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"
关于这一点的注释:您将不得不添加对System.Web.Helpers
程序集的引用。
当然,并不是每个人都喜欢dynamic
,有些人更喜欢拥有定义明确的数据合同。对于他们来说,解决方案要长一些:
您必须为数据合同创建匹配的类,并相应地赋予它们属性:
// 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; } }
您可以将成员标记为具有IgnoreDataMember
属性,以便忽略它们,或添加IsRequired=true
使其成为必需属性。
定义了这些合同之后,您可以轻松地将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" }
注意:DataContractJsonSerializer
驻留在System.ServiceModel.Web
程序集中,因此您必须为此添加引用。(当然还有System.Runtime.Serialization
组装。)
为了使它更易于使用,可以在数据协定类中添加static 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; } }
就像LB在他们的评论中提到的那样,JavaScriptSerializer
如果添加了对System.Web.Extensions
程序集的引用,则可以使用它来简化操作:
var person = new JavaScriptSerializer().Deserialize(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }");
为此,您仍然需要上面的类,但是如果愿意,可以省略-“ ugly”-属性。(但是使用这种方法,您将无法将零件标记为强制性...)