Need help to decode JSON

Hi,

I am using the ArduinoJSON library and I am heaving troubles to use it for my JSON response I get from a server.
My JSON response:

{"results":[{"series":[{"name":"sensors","columns":["time","last"],"values":[["1970-01-01T00:00:00Z",1.57]]}]}]}

My code:

void parseJSON(char json[]){
  Serial.println("to parse: " + String(json));
  StaticJsonBuffer<500> jsonBuffer;
  
  JsonObject& root = jsonBuffer.parseObject(json);
  
  if (!root.success()) {
    Serial.println("parseObject() failed");
    return;
  } else{
      Serial.println("parseObject() successful");
  }
  
  JsonObject& ooo = root["results"];
  if (!ooo.success()) {
    Serial.println("parseObject() failed");
    return;
  } else{
      Serial.println("parseObject() successful");
  }
    
  //const char* test = root["results"];
  //long time = root["results"]["series"][0];
  //const char* kWh = root["series"]["values"][1];
  const char* kWh1 = ooo["results"]["series"]["values"][1];
  double kWh2 = ooo["series"]["values"][1];

  //Serial.println(String(kWh));
  Serial.println(String(kWh1));
  Serial.println(kWh2);

}

My code prints the correct JSON at the beginning of my function and the JSON gets parsed successfully. So the buffer is big enough. But I have not found a solution to get to the number 1.57 at the end of the JSON.
I would be very grateful if you could help me to solve this problem and to learn how to parse JSON data.

Kind regards,
Tom

Have a look at the strtok() function.

First, you really shouldn't use the String class in your sketch, especially since you are using RAM to hold things that need to get parsed. String can really get you into trouble when other things (Ethernet, JSON) are using lots of RAM. Here is your routine without String:

void parseJSON(char json[]){
  Serial.print( F("to parse: ") );
  Serial.println( json );
  StaticJsonBuffer<500> jsonBuffer;
  
  JsonObject& root = jsonBuffer.parseObject(json);
  
  if (!root.success()) {
    Serial.println( F("parseObject() failed") );
    return;
  } else{
      Serial.println( F("parseObject() successful") );
  }
  
  JsonObject& ooo = root["results"];
  if (!ooo.success()) {
    Serial.println( F("parseObject() failed") );
    return;
  } else{
      Serial.println( F("parseObject() successful") );
  }

  //const char* test = root["results"];
  //long time = root["results"]["series"][0];
  //const char* kWh = root["series"]["values"][1];
  const char* kWh1 = ooo["results"]["series"]["values"][1];
  double kWh2 = ooo["series"]["values"][1];

  //Serial.println( kWh );
  Serial.println( kWh1 );
  Serial.println( kWh2 );

}

(The F macro in the Serial.prints saves a bunch of RAM.) The author of the JSON library even mentions that you shouldn't use String here. You can just print the char[] array, integer or floating-point number... you don't have to convert to String to print them.

I have not found a solution to get to the number "1.57".

I've never used the JSON library, but it looks like the array index starts at 0, like C arrays. Your JSON is a mess of nested arrays, so I have use indentation to traverse it:

{"results":
    [
      {"series":
          [
             {"name":"sensors",
               "columns":["time","last"],
               "values":
                   [
                      ["1970-01-01T00:00:00Z",1.57]
                   ]
             }
          ]
      }
    ]
}

... so maybe this is what you want:

   JsonObject& seriesArray = ooo[0] ["series"]; // results[0] is a structure with 1 member
  JsonObject& series      = seriesArray[0]; // the first array element is a structure with 3 members
  JsonObject& valuesArray = series["values"]; // an array of value arrays
  JsonObject& values      = valuesArray[0]; // a nested array of values [char * and float]

  const char *datetime = values[0];
  float       kWh1     = values[1];

You can also print these pieces to verify that you're traversing the JSON structure correctly. BTW, on the 8-bit Arduinos (UNO, Mega, Micro etc.), double is just a float.

And like UKHeliBob is suggesting, I'd be tempted to scan the response as it comes in, instead of buffering it all in one spot, parsing it with the JSON library, and accessing the resulting structure. The scanning approach would watch for certain character sequences (e.g., "values", colon and brackets) and then the numeric values. That's more of an FSM approach, and is tailored for a specific JSON response format. It's less flexible, but uses less RAM and (probably) less program space.

Cheers,
/dev