JsonParserGeneratorRK not closing JSON

Hi,

I’m testing out the JsonParserGeneratorRK library and it appears that the JSON pulled from jw.getBuffer() is not closed properly. Here is my function:

    /*HUE control brightness                        */
    /*If brightness is 0,the light is off.            */
    /*The Greater the brightness, the brighter the light.*/
    /*The range of brightness is 1~254              */
    void controlBrightness(bool power, int light, int brightness){
    
      if(power){
       JsonWriterStatic<256> jw;
        {
          JsonWriterAutoObject obj(&jw);
          
          request.path = buildHueAPIURL("lights",light);
          jw.insertKeyValue("on", power);
          jw.insertKeyValue("light", light);
          jw.insertKeyValue("bri", brightness);

        //   request.body = jw.getBuffer();
        //   http.put(request, response, headers);

          Particle.publish("brightness", jw.getBuffer(), PRIVATE);
        }
      }
    }

In Particle console the event data looks like this: {“on”:true,“bri”:151,“light”:8

Note the missing closing bracket.

@rickkas7, any ideas why this would be happening?

Thanks.

Nolan

Solved this by adding jw.finishObjectOrArray(); after the last insertKeyValue(key, value).

Note: I installed the library locally using Particle Workbench, not web IDE. Also, it’s not evident in the library example files that this is necessary. For example, in the library demo/example file [generator-JsonParserGeneratorRK.cpp] I would have expected the strcmp to fail since there is no trailing brace.

#include "Particle.h"
#include "JsonParserGeneratorRK.h"

const unsigned long TEST_RUN_PERIOD_MS = 10000;
unsigned long lastRun = 0;

void runTest();


void setup() {
	Serial.begin(9600);
}

void loop() {
	if (millis() - lastRun >= TEST_RUN_PERIOD_MS) {
		lastRun = millis();
		runTest();
	}
}

void runTest() {
	// This creates a buffer to hold up to 256 bytes of JSON data (good for Particle.publish)
	JsonWriterStatic<256> jw;

	// Creating a scope like this in {} with a JsonWriterAutoObject in it creates an object,
	// and automatically closes the object when leaving the scope. This is necessary because
	// all JSON values must be in either an object or an array to be valid, and JsonWriter
	// requires all startObject to be balanced with a finishObjectOrArray and JsonWriterAutoObject
	// takes care of doing that automatically.
	{
		JsonWriterAutoObject obj(&jw);

		// Add various types of data
		jw.insertKeyValue("a", true);
		jw.insertKeyValue("b", 1234);
		jw.insertKeyValue("c", "test");
	}

	// Verify the results
	if (strcmp(jw.getBuffer(), "{\"a\":true,\"b\":1234,\"c\":\"test\"}")) {
		Serial.printlnf("test mismatch got %s", jw.getBuffer());
		return;
	}


	Serial.println("test passed!");
}

The Particle.publish must be on the other side of the } below it.

The JsonWriterAutoObject must go out of scope to close the object, so you want to publish after it’s closed.

1 Like

Doh! not sure how I missed that! Thanks @rickkas7.

I’m having a similar problem. Originally I declared JsonWriterStatic<256> jw; as a global variable, however I keep getting multiple sets of readings in the {{{PARTICLE_EVENT_VALUE}}} field. I moved it inside the function and now I only get the current reading. Problem is, the Json object is no longer closing.

void createEventPayLoad(int temp, int humidity, int pressure, String airQuality)
{
    JsonWriterStatic<256> jw;
    JsonWriterAutoObject obj(&jw);
    
    {
        jw.insertKeyValue("temp", temp);
        jw.insertKeyValue("humidity", humidity);
        jw.insertKeyValue("pressure", pressure);
        jw.insertKeyValue("airquality", airQuality);
    
       //if (lowpulseoccupancy > 0)
        //{
        //    jw.insertKeyValue("lowpulseoccupancy", lowpulseoccupancy);
        //    jw.insertKeyValue("ratio", ratio);
        //    jw.insertKeyValue("concentration", concentration);
        //}
    }

    Particle.publish("data", jw.getBuffer(), PRIVATE);
}

2020-03-11

You need to put the JsonWriterAutoObject obj(&jw); inside the curly brackets because the object needs to go out of scope before you publish the value.

Also, if you want to put it in a global variable, just do a jw.clear() before creating the AutoObject.

1 Like