Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding keys to object in a loop #84

Closed
SeanDS opened this issue Jun 25, 2015 · 4 comments
Closed

Adding keys to object in a loop #84

SeanDS opened this issue Jun 25, 2015 · 4 comments
Labels
question v5 ArduinoJson 5

Comments

@SeanDS
Copy link

SeanDS commented Jun 25, 2015

I am having trouble adding keys to a JsonObject within a loop:

#include <ArduinoJson.h>

// output pins
unsigned int outputPins[8] = {2, 3, 5, 6, 7, 8, 9, 11};

// number of defined pins in list
const int NUMBER_OF_OUTPUTS = (sizeof(outputPins) / sizeof(int));

void setup()
{
  // open serial communications and wait for port to open:
  Serial.begin(9600);

  StaticJsonBuffer<1024> jsonBuffer;

  JsonObject& root = jsonBuffer.createObject();

  for (int i = 0; i < NUMBER_OF_OUTPUTS; i++) {   
    String key = String("pin_") + String(i);

    Serial.print("Key: ");
    Serial.print(key);

    String message = String(i);

    Serial.print(", index: ");
    Serial.println(message);

    root.set(key, i);
  }

  root.printTo(Serial);
}

This outputs on the serial terminal:

Key: pin_1, index: 1
Key: pin_2, index: 2
Key: pin_3, index: 3
Key: pin_4, index: 4
Key: pin_5, index: 5
Key: pin_6, index: 6
Key: pin_7, index: 7
{"pin_7":7}

So only the last iteration of the loop is added to the object. I guess the same value is being overwritten in each iteration, but I can't figure out why.

I'm using v5.0beta1. I know you don't encourage the use of String() but I tried to figure out a way to do this with chars and it was even less successful (meaningless garbage was printed, mostly).

Any help would be greatly appreciated! This is an excellent tool - thanks a lot for sharing it.

@bblanchon
Copy link
Owner

Hi Sean,

This is a tough one. Several users felt into this trap (see #10, #57).

The reason is that, for performance reasons, ArduinoJson never makes copies of the strings.
In your program, you're reusing the same memory location to store all the keys, so ArduinoJson sees it at the same key.

It may look strange if you come from Java or C#, but C++ works that way.
In your program the variable key it deleted at the end of each loop iteration, and it is reused at the next loop iteration.

The solution is to allocate the memory outside of the loop.

Here is a suggestion:

const char* keys[] = {
    "pin_0",
    "pin_1",
    "pin_2",
    "pin_3",
    // up to NUMBER_OF_OUTPUTS
};

for (int i = 0; i < NUMBER_OF_OUTPUTS; i++) {   
    root.set(keys[i], i);
}

You should also consider using a JsonArray, as it seems more appropriate here.

Thanks for using the beta version, this is really helping me 😉

Regards,
Benoit

@SeanDS
Copy link
Author

SeanDS commented Jun 26, 2015

That worked - thanks very much! This has indeed exposed my lack of C++ exposure.

May I suggest that the wiki contains a small warning about this?

So far everything in 5.0beta1 is working as expected - good job!

@bblanchon
Copy link
Owner

bblanchon commented Jun 26, 2015

I added section 6. Do not assume that strings are copied.
Don't hesitate to improve the wiki.

@SeanDS
Copy link
Author

SeanDS commented Jun 27, 2015

Thanks, will do!

Repository owner locked and limited conversation to collaborators Sep 21, 2018
@bblanchon bblanchon added the v5 ArduinoJson 5 label Feb 6, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
question v5 ArduinoJson 5
Projects
None yet
Development

No branches or pull requests

2 participants