0

I need to deserialize the following JSON:

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

I am using the following C# code to deserialize the above 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;
}

And

[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; }
}

Surely there is a better way to get hold of the array of "record" under "records" that makes this scalable instread of defining each record individualy in the code. I know that a JSON reader can be used, but would prefer a simple deserialze routine.

I want to be able to deserialize the JSON into a list of records (e.g. List, how do I achieve this?

1
  • "Parse/Deserialze JSON in C# where there are named items in the array" There is no array in your quoted JSON. Your quoted JSON is also incomplete, at a minimum it would need { and } around it. Commented Mar 26, 2015 at 8:45

3 Answers 3

1

I think in you case it would be better to remove Records class at all and and in Response class change type of Records property to IDictionary<string, Record>. So your class structure might look like that:

[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; }
}

You can always think of JSON as IDictionary<string, object> in C#. It makes understanding of JSON much easier.

I also suggest to use Name property of DataMember attribute because you can keep C# property naming according to guidelines.

Sign up to request clarification or add additional context in comments.

1 Comment

This worked perfectly, I just needed to use JSON.Net
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; }
}

Comments

0

Solution is simple your json format

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

can be parsed with json.net in a simple and powerfull way with this code

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);
}

We get all the records into a jobject list then parse each of them in the simplest way ever and add each record to a list

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.