简体   繁体   中英

Deserializing json in c# for the nest-api

I am trying trying to Deserialize the Devices json structure below with c#, newtonsoft, and .net 3.5, put have been unable to produce code that works as the "qxdddh" and "q0tL6au" are dynamically generated names.

Ultimately creating a list or array of thermostat classes for each thermostat in the structure (in this case "qxdddh" and "q0tL6au").

{
    "thermostats": {
        "qxdddh": {
            "locale": "en-US",
            "temperature_scale": "F",
            "is_using_emergency_heat": false,
            "has_fan": true,
            "software_version": "4.1",
            "has_leaf": true,
            "device_id": "qxdddh",
            "name": "",
            "can_heat": true,
            "can_cool": true,
            "hvac_mode": "heat",
            "target_temperature_c": 12.5,
            "target_temperature_f": 55,
            "target_temperature_high_c": 24.0,
            "target_temperature_high_f": 75,
            "target_temperature_low_c": 20.0,
            "target_temperature_low_f": 68,
            "ambient_temperature_c": 21.0,
            "ambient_temperature_f": 70,
            "away_temperature_high_c": 24.0,
            "away_temperature_high_f": 76,
            "away_temperature_low_c": 12.5,
            "away_temperature_low_f": 55,
            "structure_id": "ryWu-tRQstxux0tYhmZ8ESsrGgDjDQ",
            "fan_timer_active": false,
            "name_long": "Thermostat",
            "is_online": true
        },
        "q0tL6au": {
            "locale": "en-US",
            "temperature_scale": "F",
            "is_using_emergency_heat": false,
            "has_fan": true,
            "software_version": "4.1",
            "has_leaf": true,
            "device_id": "q0tL6au",
            "name": "Den",
            "can_heat": false,
            "can_cool": true,
            "hvac_mode": "off",
            "target_temperature_c": 20.5,
            "target_temperature_f": 69,
            "target_temperature_high_c": 24.0,
            "target_temperature_high_f": 75,
            "target_temperature_low_c": 20.0,
            "target_temperature_low_f": 68,
            "ambient_temperature_c": 23.0,
            "ambient_temperature_f": 73,
            "away_temperature_high_c": 24.0,
            "away_temperature_high_f": 76,
            "away_temperature_low_c": 12.5,
            "away_temperature_low_f": 55,
            "structure_id": "ryWu-tqNu0tYhmZ8ESsrGgDjDQ",
            "fan_timer_active": false,
            "name_long": "Den Thermostat",
            "is_online": true
        }
    }
}

The initial attempt of code was

    public class Devices
    {
        public TstatDetails[] thermostats { get; set; }
    }

    public class TstatDetails
    {
         public string locale { get; set; }
         public string temperature_scale { get; set; }
         public string is_using_emergency_heat { get; set; }
         public string has_fan { get; set; }
         public string software_version { get; set; }
         public string has_leaf { get; set; }
         public string device_id { get; set; }
         public string name { get; set; }
         public string can_heat { get; set; }
         public string can_cool { get; set; }
         public string hvac_mode { get; set; }
         public string target_temperature_c { get; set; }
         public string target_temperature_f { get; set; }
         public string target_temperature_high_c { get; set; }
         public string target_temperature_high_f { get; set; }
         public string target_temperature_low_c { get; set; }
         public string target_temperature_low_f { get; set; }
         public string ambient_temperature_c { get; set; }
         public string ambient_temperature_f { get; set; }
         public string away_temperature_high_c { get; set; }
         public string away_temperature_high_f { get; set; }
         public string away_temperature_low_c { get; set; }
         public string away_temperature_low_f { get; set; }
         public string structure_id { get; set; }
         public string fan_timer_active { get; set; }
         public string name_long { get; set; }
         public string is_online { get; set; }
    }

and

Devices tstats = (Devices) Newtonsoft.Json.JsonConvert.DeserializeObject<Devices>(jsonstring);

Which produces and exception with the following description

Cannot deserialize the current JSON object (eg {"name":"value"}) into type 'NestTest.NestOAuth2+TstatDetails[]' because the type requires a JSON array (eg [1,2,3]) to deserialize correctly.

To fix this error either change the JSON to a JSON array (eg [1,2,3]) or change the deserialized type so that it is a normal .NET type (eg not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.

I understand the error (i think) but being fairly new to c# am unsure on how to correct for this scenario.

Just change your Devices class to use a Dictionary<,> instead of an array:

public class Devices
{
    public Dictionary<string, TstatDetails> thermostats { get; set; }
}

JSON.NET will interpret each property of the thermostats object in the JSON as an entry in the dictionary, and populate it appropriately. (Your calling code remains exactly the same.)

Then you'll have all the thermostats available by ID. For example:

TstatDetails details = tstats["qxdddh"];

Once that's working, I'd strongly recommend you try to make all the property names more conventional :)

Your Json object should be an array, not just an object.

It should basically be wrapped with [ .... ] (of which within you can definitely have multiple objects ) rather than { ... } .

It should probably look similar to this:

[
        {
            "locale": "en-US",
            "temperature_scale": "F",
            "is_using_emergency_heat": false,
            ...
        },
        {
            "locale": "en-US",
            "temperature_scale": "F",
            "is_using_emergency_heat": false,
            ...
        }
]

EDIT

OK, I can't compete with The Skeet. But I'll leave my answer because it's correct as well (just one option to attack the problem).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM