Setting ArduinoJson value from C++ STL Containers (std::vector, std::array, etc)
If you are creating your own std::vector in c++ code (platformio in my case), and need to set the value on one of your JsonObject or JsonArray for Arduino, there’s a specific function/method you can use to do this, and below are some examples and how to do it.
First I must say thank you to @timemage in the #arduino channel on Freenode, who helped me to figure this out.
In my situation I was storing a dynamic number of values into an array during the normal loop() in Arduino code, and at some point in there, I needed to send that data, along with a matching JSON structure before inserting it into a Mongo database … which btw MongoDB is .. sooooo … awesome, esp coming from MySQL … yikes!
My array was using just std::vector<double> but for the life of me I couldn’t figure out how to set that value in a key of a JsonObject I created using ArduinoJson. With a lot of my coding skills being PHP or JavaScript (web based) , it was quite difficult to understand that I couldn’t just set the variable equal to that array .. and I think that comes with more experience in lower level programming languages.
My code for the vector looked like this, which uses STL container std::vector:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
std::vector<double> _flowPulses; std::vector<double> _flowRate; void loop(){ // Do something here special (removed for simplicity) _currentPulses = 1; _flowRate = 1; _flowPulses.push_back( _currentPulses ); _flowRate.push_back( flowRate ); // And something here special (removed for simplicity) } |
Set ArduinoJson array from std::vector
So to set the value of JsonArray& that we created, you have to use the .copyFrom which you can find documentation (https://arduinojson.org/api/jsonarray/copyfrom/), setting the first value equal to the variable used, calling the .data() function/method, and the second one equal to the variable calling .size(), like so:
1 2 3 4 |
JsonArray& rate = data.createNestedArray("rate"); pulses.copyFrom( _flowPulses.data(), _flowPulses.size() ); rate.copyFrom( _flowRate.data(), _flowRate.size() ); |
That’s all there is to it. Yes it may sound simple, but I spent hours trying to figure this out due to the way that memory is allocated for arrays, and really just only having a bit of C++ knowledge, so hopefully if someone else has this issue, this post helps you out 🙂
Working Code
Here’s the code that actually works (i’ll keep the 20x revisions that didn’t work — to myself hah):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
// Use dynamic since i'm running on ESP8266 DynamicJsonBuffer jsonBuffer; // Create root object {} JsonObject& mist = jsonBuffer.createObject(); // Set a few top level values mist["start"] = _startTime; mist["end"] = _endRuntime; // Result: // { // start: 12345, // end: 12345 // } // Create a data key in the object to store data in JsonObject& data = mist.createNestedObject("data"); // { // start: 12345, // end: 12345, // data: {} // } // Create two arrays that will be in the object JsonArray& pulses = data.createNestedArray("pulses"); JsonArray& rate = data.createNestedArray("rate"); // // { // start: 12345, // end: 12345, // data: { // pulses: [], // rate: [] // } // } pulses.copyFrom( _flowPulses.data(), _flowPulses.size() ); rate.copyFrom( _flowRate.data(), _flowRate.size() ); // // { // start: 12345, // end: 12345, // data: { // pulses: [1,2,3,4,5], // rate: [5,4,3,2,1] // } // } // Create a string to store the JSON in String mistJSON; // Print the JSON to the string above, now mistJSON = {..} mist.printTo( mistJSON ); |
Voila! Profit!