簡體   English   中英

如何將JSON字符串反序列化為C#對象?

[英]How to deserialize JSON string into a C# object?

考慮以下幾點:您有一個返回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程序集。)

為了使其更易於使用,可以將靜態ParseTryParse方法添加到數據協定類:

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在他們的評論中提到的那樣,如果添加對System.Web.Extensions程序集的引用,則可以使用JavaScriptSerializer使其更簡單:

var person = new JavaScriptSerializer().Deserialize<Person>(@"{ ""Name"": ""Jon Smith"", ""Address"": { ""City"": ""New York"", ""State"": ""NY"" }, ""Age"": 42 }");

為此,您仍然需要上面的類,但是如果願意,可以省略-“ ugly”-屬性。 (但是使用這種方法,您將無法將零件標記為強制性...)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM