0

I am writing an app to control Philips Hue smartlights using their REST API and Square's Retrofit library.

The problem is, when I make a call to /lights the response comes back using each light's id property as the key in the json response (rather than an array of light objects that is typical in a jsonapi response, and that seems to be expected by Retrofit).

Here is the request/response I'm looking at

GET /lights

returns

``` {

"1": {
    "state": {
        "on": true,
        "bri": 144,
        "hue": 13088,
        "sat": 212,
        "xy": [0.5128,0.4147],
        "ct": 467,
        "alert": "none",
        "effect": "none",
        "colormode": "xy",
        "reachable": true
    },
    "type": "Extended color light",
    "name": "Hue Lamp 1",
    "modelid": "LCT001",
    "swversion": "66009461",
    "pointsymbol": {
        "1": "none",
        "2": "none",
        "3": "none",
        "4": "none",
        "5": "none",
        "6": "none",
        "7": "none",
        "8": "none"
    }
},
"2": {
    "state": {
        "on": false,
        "bri": 0,
        "hue": 0,
        "sat": 0,
        "xy": [0,0],
        "ct": 0,
        "alert": "none",
        "effect": "none",
        "colormode": "hs",
        "reachable": true
    },
    "type": "Extended color light",
    "name": "Hue Lamp 2",
    "modelid": "LCT001",
    "swversion": "66009461",
    "pointsymbol": {
        "1": "none",
        "2": "none",
        "3": "none",
        "4": "none",
        "5": "none",
        "6": "none",
        "7": "none",
        "8": "none"
    }
}

} ```

Notice how instead of returning an array of light objects, it returns each light object keyed off its light id.

Anyone have an idea of how to parse this with Retrofit?

johncorser
  • 9,262
  • 17
  • 57
  • 102
  • Do you use GSON or smething like this? AFAIR GSON can't parse regexes for annotated fields, so looks like the best way is to use Jackson library for parsing and manually convert it to array. – MightySeal Jun 29 '15 at 14:34

2 Answers2

1

Retrofit uses GSON to deserialize the json it receives, which in turn uses a class to understand the json you are feeding it.

In Gson you can also create a custom deserializer, there are many resources up for learning how to create one.

What you can do in the deserializer is to get the keyset of the json object and iterate over it. You can get the keyset like

Set<Map.Entry<String, JsonElement>> nodeSet = jsonObject.entrySet();

Iterate over this nodeSet and the

for(Map.Entry<String, JsonElement> entryItem : nodeSet) {
        JsonObject currentValue = entryItem.getValue().getAsJsonObject();
}

The currentValue would the JsonObject containing the "state", "type" etc elements.

Sahil Dave
  • 433
  • 1
  • 7
  • 15
0

Based on the answer from this StackOverflow question Retrofit parse JSON dynamic keys

Use a class which contains a single map field

class Lights { 
    // key is id of the light
    // value is the Light object which contains all the attributes
    Map<String, Light> allLights;
}

class Light {
    // all the attributes
    State state;
    String type;
    ...
}
Community
  • 1
  • 1
desmondtzq
  • 386
  • 3
  • 10