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

Problem with nested objects #497

Closed
bcatalin opened this issue May 2, 2017 · 8 comments
Closed

Problem with nested objects #497

bcatalin opened this issue May 2, 2017 · 8 comments
Labels
v5 ArduinoJson 5

Comments

@bcatalin
Copy link

bcatalin commented May 2, 2017

Hi,

I have a issue reading (or writing) a nested JSON on an ESP8266.
What I try to have is a file is [ {"m":1, "h":2} , {"m":10, "h":20} , {"m":100, "h":200} ]

I am using SPIFFS to write the JSON to a file then to read it.

For one object is working fine, but for nested array does not working at all.

Code below:

Not working case:

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ArduinoJson.h>
#include "FS.h"

void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
delay(2000);
int i=0;
if( SPIFFS.begin() )
{
File my_file = SPIFFS.open("xfile.json", "w");
if (!my_file) {
Serial.println("failed to open xfile.json file for writing :-(");
return; //==============>
}
StaticJsonBuffer<300> jsonBuffer;
JsonArray& my_array = jsonBuffer.createArray();
for(i=0;i<3;i++)
{
JsonObject& my_entry = my_array.createNestedObject();
my_entry["m"] = 20;
my_entry["h"] = 14;
}
my_array.printTo(Serial);
Serial.println("");
my_array.printTo(my_file);
my_file.close();
delay(1000);
//---------------------------- READ ----------------------------------
File myFile = SPIFFS.open("xfile.json", "r");
if (myFile)
{
Serial.println("opened xfile.json file");
size_t size = myFile.size();
// Allocate a buffer to store contents of the file.
std::unique_ptr<char[]> buf(new char[size]);
Serial.println(size);
Serial.println(buf.get());
myFile.readBytes(buf.get(), size);
DynamicJsonBuffer jsonBuffer;
//StaticJsonBuffer<200> jsonBuffer;
JsonObject& jsona = jsonBuffer.parseObject(buf.get());
jsona.printTo(Serial);
Serial.println("");
if (jsona.success())
{
Serial.println("READ OK");
}
else
{
Serial.println("Json invalid");
}
}
myFile.close();
}//end SPIFFS.begin
}//end setup
void loop() {
// put your main code here, to run repeatedly:
}

and working case:

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ArduinoJson.h>
#include "FS.h"

void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
delay(2000);
int i=0;
if( SPIFFS.begin() )
{
File my_file = SPIFFS.open("xfile.json", "w");
if (!my_file) {
Serial.println("failed to open xfile.json file for writing :-(");
return; //==============>
}

StaticJsonBuffer<300> jsonBuffer;
JsonObject& my_entry = jsonBuffer.createObject();
my_entry["m"] = 20;
my_entry["h"] = 14;

my_entry.printTo(Serial); 
Serial.println("");
my_entry.printTo(my_file);
my_file.close();

delay(1000);
//---------------------------- READ ----------------------------------

File myFile = SPIFFS.open("xfile.json", "r");
if (myFile) 
{
    Serial.println("opened xfile.json file");
    size_t size = myFile.size();
    // Allocate a buffer to store contents of the file.
    std::unique_ptr<char[]> buf(new char[size]);
    Serial.println(size);
    Serial.println(buf.get());
    myFile.readBytes(buf.get(), size);
    DynamicJsonBuffer jsonBuffer;
    //StaticJsonBuffer<200> jsonBuffer;        
    JsonObject& jsona = jsonBuffer.parseObject(buf.get());
    jsona.printTo(Serial);
    Serial.println("");
    if (jsona.success()) 
    { 
      Serial.println("READ OK");
    }
    else
    {
      Serial.println("Json invalid");
    }
}
myFile.close();

}//end SPIFFS.begin
}//end setup

void loop() {
// put your main code here, to run repeatedly:

}

@bblanchon
Copy link
Owner

Hi,

I don't know what's wrong, but I think you should simplify your code by removing buf:

File myFile = SPIFFS.open("xfile.json", "r");
if (myFile) 
{
    DynamicJsonBuffer jsonBuffer;
    JsonObject& jsona = jsonBuffer.parseObject(myFile);
    // ...
}
myFile.close();

I didn't test, but I think it should work as File derives from Stream.

@bcatalin
Copy link
Author

bcatalin commented May 4, 2017

Ok, I'll give it a try, But if I provide to parseObject a String like [{"a":1,"b":2},{"a":12,"b":22}] it will able to parse it right ?

@bblanchon
Copy link
Owner

bblanchon commented May 6, 2017

Yes, but this approach uses more memory because you make a full copy of the file in memory.

See:

@bcatalin
Copy link
Author

bcatalin commented May 6, 2017

That is correct, but the array I need will have maximum 10 objects in it and only during the start of the card, so is fine for my project. But you are right about memory.

@bcatalin
Copy link
Author

bcatalin commented May 7, 2017

I've found that the SPIFFS might have a problem reading data that starts an ends with [], but is not clear for me why this library can not decode an array of JSONs.
This basic code is failing.

#include <ArduinoJson.h>

void setup() {
  Serial.begin(115200);
  Serial.println("");
  StaticJsonBuffer<200> jsonBuffer;

  char json[] = "[{\"a\":1, \"b\":2},{\"a\":11, \"b\":22}]";

  JsonObject& root = jsonBuffer.parseObject(json);

  // Test parsing.
  if (!root.success()) 
    Serial.println("parseObject() failed");    
  else
    Serial.println("all good");
}

void loop() {
  // not used 
}

My expectation is that after root.success returns TRUE, to iterate over the number of JSONs like

int elements = 2;
int i=0;
for(i=0; i<elements; i++)
{
  Serial.println(root["a"]; //print 1 first, print 11 on second pass
  Serial.println(root["b"]; //print 2 first, print 22 on second pass
}

It is possible ?
In the non Arduino IDE I've used cJSON to do it and was ok, but now I am moving all the code to Arduino IDE and this is the last issue I have. Thanks.

@bblanchon
Copy link
Owner

bblanchon commented May 7, 2017

Hello Catalin,

You need to call parseArray() instead of parseObject().

See:

@bcatalin
Copy link
Author

bcatalin commented May 7, 2017

Right! Another case for RTFM :-)

@bblanchon
Copy link
Owner

That was not my point.
I'm adding a link to the FAQ so that other users will find it.

You're not the first to make that mistake, so I probably missed something as a library author.
What could have prevented you from making that mistake?
Would JsonObject& obj = jsonBuffer.parse<JsonObject>(json); be better?

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
v5 ArduinoJson 5
Projects
None yet
Development

No branches or pull requests

2 participants