5

I'm trying to deserialize a JSON response from an API. The JSON looks like this (MAC addresses and location are altered):

{
"body" : [{
        "_id" : "da:87:54:26:53:97",
        "place" : {
            "location" : [-23.334961, 47.398349],
            "altitude" : 30,
            "timezone" : "Europe\/London"
        },
        "mark" : 3,
        "measures" : {
            "f2:bf:a7:6f:e7:e8" : {
                "res" : {
                    "1469997248" : [20.4, 66]
                },
                "type" : ["temperature", "humidity"]
            },
            "42:b7:48:59:7c:4b" : {
                "res" : {
                    "1469997263" : [1016.7]
                },
                "type" : ["pressure"]
            }
        },
        "modules" : ["f2:bf:a7:6f:e7:e8"]
    }
],
"status" : "ok",
"time_exec" : 0.034152030944824,
"time_server" : 1469997417
}

The problem is the measures block. Since the name of the object is changing, I don't know how to deserialize it properly into a C# object. I found a similiar problem on here with the solution to use a dictonary, however if I try it this way I just get null directory.

This is my deserialize method:

APIResponse apiResponse = JsonConvert.DeserializeObject<APIResponse>(await content.ReadAsStringAsync());

And this is the APIResponse class:

public class APIResponse
{
    public Body[] body { get; set; }
    public string status { get; set; }
    public float time_exec { get; set; }
    public int time_server { get; set; }
}

public class Body
{
    public string _id { get; set; }
    public Place place { get; set; }
    public int mark { get; set; }
    public Measures measures { get; set; }
    public string[] modules { get; set; }
}

public class Place
{
    public float[] location { get; set; }
    public float altitude { get; set; }
    public string timezone { get; set; }
}

public class Measures
{
   public Dictionary<string, SingleModule> singlemodules{ get; set; }
}

public class SingleModule
{
    public Res res { get; set; }
    public string[] type { get; set; }
}

public class Res
{
    public MeasuredData measuredData { get; set; }
}
public class MeasuredData
{
    public float[] values { get; set; }
}

Any way to properly derserialize the measures easily?

Community
  • 1
  • 1
Nirusu
  • 55
  • 1
  • 8

1 Answers1

16

It looks like you should be able to just get rid of your Measures class. Instead, put the dictionary straight into your Body class:

public class Body
{
    public string _id { get; set; }
    public Place place { get; set; }
    public int mark { get; set; }
    public Dictionary<string, SingleModule> measures { get; set; }
    public string[] modules { get; set; }
}

As a separate matter, I'd strongly recommend following .NET naming conventions for your properties, and using [JsonProperty("measures")] etc to indicate to Json.NET how to translate your properties into JSON.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • The namings are messed up because they were generated from the JSON and I haven't really edited them yet. Anyway, this solution works. Thanks! – Nirusu Jul 31 '16 at 21:55
  • Well, I just noticed that I've got a similar problem with the child object of `res`, which also has a changing name. How can I fix this? – Nirusu Jul 31 '16 at 22:39
  • 1
    @Niruga: The same way again - get rid of the `Res` class, and use a `Dictionary` or a `Dictionary>` – Jon Skeet Jul 31 '16 at 22:40
  • Whoops, I tried doing it this way before asking again but I used `Dictionary` and wondered why it threw an exception. Changed it, got rid of the `Res` and `MeasuredData` classes and now it works! My bad, and thanks again! – Nirusu Jul 31 '16 at 22:47