AndroidJSON parsing nested GET-Response

1.1k Views Asked by At

I'am trying to iterate over a nested JSON-Object which i get as a HTTP-GET Response from my Hue-Bridge. The Response is something like this:

{
    "name": "ViKo",
    "type": "GroupScene",
    "group": "2",
    "lights": [
        "1",
        "2",
        "6",
        "9",
        "11",
        "17",
        "18"
    ],
    "recycle": false,
    "locked": false,
    "picture": "",
    "version": 2,
    "lightstates": {
        "1": {
            "on": false,
            "bri": 254,
            "ct": 230
        },
        "2": {
            "on": false,
            "bri": 254,
            "ct": 230
        },
        "6": {
            "on": true,
            "bri": 254,
            "ct": 230
        },
        "9": {
            "on": false,
            "bri": 254,
            "ct": 230
        },
        "11": {
            "on": true,
            "bri": 254,
            "ct": 230
        },
        "17": {
            "on": true,
            "bri": 254,
            "ct": 230
        },
        "18": {
            "on": true,
            "bri": 254,
            "ct": 230
        }
    }
}

Now i am interested in the member lightstates and the containing sub objects and iterating over the subitems with a loop (or something like thsi).

My Arduino (NodeMCU)-Code looks something like this:

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <ArduinoJson.h>

void loop()
{

  if (digitalRead(BUTTON) == HIGH)
  {

    //Check WiFi connection status
    if (WiFi.status() == WL_CONNECTED)
    {
      HTTPClient http;
      WiFiClient client;

      http.begin(client, BRIDGE_SCENE_URL + SCENE_VIKO);

      int httpCode = http.GET();
      String payload = http.getString();

      if (httpCode == 200)
      {
        const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60;

        DynamicJsonDocument doc(capacity);
        deserializeJson(doc, payload);
        JsonObject root = doc.as<JsonObject>();

        JsonObject name = root.getMember("lightstates").as<JsonObject>();

        for (JsonPair kv : name)
        {
          Serial.println(kv.key().c_str());
        }

      }

      http.end(); //Close connection

      delay(500);
    }

  }

}

So i am getting a valid json response from the Bridge but the for-loop does not print anything. The goal ist to iterate over lightstates and put the values in a method with signature similar to

void changeLightState(int id, boolean on, int bri, int ct)

It would be great if anyone has an idea for me.

1

There are 1 best solutions below

0
On

If you look closely to the json object, lightstates is an JsonObject, within it, each light is another JsonObject consists of light state of each light, so you are dealing with an object within an object of another object.

So it take a little bit more to get the data you want, here is the example:

#include <ArduinoJson.h>

String in = "{\"lightstates\": {\"1\": {\"on\": false,\"bri\": 254,\"ct\": 230},\"2\": {\"on\": false,\"bri\": 125,\"ct\": 120} } }";

void setup() {
  Serial.begin(115200);

  StaticJsonDocument<1024> doc;

  DeserializationError error = deserializeJson(doc, in);

  if (error) {
    Serial.print("deserializeJson() failed: ");
    Serial.println(error.c_str());
    return;
  }

  JsonObject lightstates = doc["lightstates"];  //get lightstates obj
  for (JsonPair light: lightstates) {           //iterate thru each light obj  
    JsonObject lightstate = light.value();      //get lightstates of each light

    int light_id = atoi(light.key().c_str());    
    bool light_on = lightstate["on"];
    int light_bri = lightstate["bri"];
    int light_ct = lightstate["ct"];

    Serial.printf("Light %d: on - %s, bri - %d, ct - %d\n", 
      light_id, 
      light_on ? "true": "false",
      light_bri, 
      light_ct
    );
  }

}

void loop() {

}

This will print out the data as:

Light 1: on - false, bri - 254, ct - 230
Light 2: on - false, bri - 125, ct - 120