在C#中解析/反序列化JSON,其中数组中有命名项

时间:2015-03-26 08:43:58

标签: c# json serialization

我需要反序列化以下JSON:

    "response": {
       "records": {
          "record-1": {
             "id": "1",
             "name": "foo"
        },
        "record-2": {                 
             "id": "2",
             "name": "foo"
        },
        "record-3": {
             "id": "3",
             "name": "foo-bar"
        }
      }
    }

我使用以下C#代码反序列化上面的JSON:

    HttpWebRequest httpWebRequest = System.Net.WebRequest.Create(requestUrl) as HttpWebRequest;
    using (HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse)
    {
        if (httpWebResponse.StatusCode != HttpStatusCode.OK)
            throw new Exception(string.Format("Server error (HTTP {0}: {1}).", httpWebResponse.StatusCode, httpWebResponse.StatusDescription));

        Stream stream = httpWebResponse.GetResponseStream());
        DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(typeof(MyResponseClass));
        objResponse = dataContractJsonSerializer.ReadObject(stream);
        if (objResponse == null)
            return null;
    }


    [DataContract]
    class MyResponseClass
    {
        [DataMember]
        public Response response { get; set; }
    }

    [DataContract]
    public class Response
    {
        [DataMember]
        public Records records { get; set; }
    }

    [DataContract]
    public class Records
    {
        [DataMember(Name = "record-1")]
        Record record_1 { get; set; }
        [DataMember(Name = "record-2")]
        Record record_2 { get; set; }
        [DataMember(Name = "record-3")]
        Record record_3 { get; set; }
    }
    [DataContract]
    public class Record
    {
        [DataMember]
        public string id { get; set; }
        [DataMember]
        public string name { get; set; }
    }

当然有更好的方法来掌握"记录"在"记录"这使得这个可扩展的instread在代码中单独定义每个记录。我知道可以使用JSON阅读器,但更喜欢简单的反序列化例程。

我希望能够将JSON反序列化为记录列表(例如List,我该如何实现?

3 个答案:

答案 0 :(得分:1)

我认为在您的情况下,最好将Records类和Response类更改类型的Records属性删除为IDictionary<string, Record>。所以你的类结构可能看起来像这样:

[DataContract]
class MyResponseClass
{
    [DataMember(Name = "response")]
    public Response Response { get; set; }
}

[DataContract]
public class Response
{
    [DataMember(Name = "records")]
    public IDictionary<string, Record> Records { get; set; }
}

[DataContract]
public class Record
{
    [DataMember(Name = "id")]
    public string Id { get; set; }

    [DataMember(Name = "name")]
    public string Name { get; set; }
}

您始终可以将JSON视为C#中的IDictionary<string, object>。它使JSON的理解变得更加容易。

我还建议使用Name属性的DataMember属性,因为您可以根据指南保留C#属性命名。

答案 1 :(得分:0)

解决方案很简单,你的json应采用这种格式

{"response": {
       "records": {
          "record-1": {
             "id": "1",
             "name": "foo"
        },
        "record-2": {                 
             "id": "2",
             "name": "foo"
        },
        "record-3": {
             "id": "3",
             "name": "foo-bar"
        }
      }
    }
	}

解析这个json使用json.net它更简单,更强大 只需运行此代码

 var recordsJson = jsonObject.SelectToken("response").SelectToken("records").Children<JProperty>().Select(p=>p.Value).ToList();
            foreach (var rec in recordsJson)
            {
                var record = JsonConvert.DeserializeObject<Record>(rec.ToString());
                Records.Add(record);
            }

我们将所有记录都记录到作业列表中,然后以最简单的方式解析每个记录并将每个记录添加到列表中

答案 2 :(得分:0)

  MyResponse myResponse = null;

  HttpWebRequest httpWebRequest = System.Net.WebRequest.Create(requestUrl) as HttpWebRequest;
  using (HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse)
  {
    if (httpWebResponse.StatusCode != HttpStatusCode.OK)
        throw new Exception(string.Format("Server error (HTTP {0}: {1}).", httpWebResponse.StatusCode, httpWebResponse.StatusDescription));

    Stream stream = httpWebResponse.GetResponseStream());
    using (StreamReader streamReader = new StreamReader(stream))
    {
        myResponse = JsonConvert.DeserializeObject<MyResponse>(streamReader.ReadToEnd());

    }
  }

  return myResponse;



[DataContract]
class MyResponseClass
{
    [DataMember]
    public Response response { get; set; }
}

[DataContract]
public class Response
{
    [DataMember(Name = "records")]
    public IDictionary<string, Record> Records { get; set; }
}

[DataContract]
public class Record
{
    [DataMember]
    public string id { get; set; }
    [DataMember]
    public string name { get; set; }
}