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

Nested arrays and structures #1723

Closed
simonemarin opened this issue Mar 3, 2022 · 5 comments
Closed

Nested arrays and structures #1723

simonemarin opened this issue Mar 3, 2022 · 5 comments
Labels
question v6 ArduinoJson 6

Comments

@simonemarin
Copy link

Describe the issue
I am trying to parse an array inside the json object and setting the data in 2 structures.
JSON model:

{
    "cameras": [
      {
        "viscaip": "192.168.5.163",
        "port": 1259,
        "channel": 1,
        "profile": "0"
      },
      {
        
        "viscaip": "192.168.5.163",
        "port": 1259,
        "channel": 10,
        "profile": "0"
      }
    ],
    "hostip": "192.168.5.102",
}

Troubleshooter report
Here is the report generated by the ArduinoJson Troubleshooter:

ArduinoJson Troubleshooter's report
  1. The issue happens at compile time
  2. The error is not in the list

Environment
Here is the environment that I'm using':

  • Microconroller: ESP32
  • Core/runtime: ESP32 2.0
  • IDE: Arduino IDE 1.8.19

Reproduction
Here is a small snippet that demonstrate the problem.

struct Camera {
  char viscaip[16];
  int port;
  int channel;
  char HEXpan[8];
  char HEXtiltUp[8];
  char HEXtiltDown[8];  
};
struct Config {
  char hostip[16];
  Camera* cam[];
};
Config config;
  StaticJsonDocument<512> doc;
  DeserializationError error = deserializeJson(doc, file);
  JsonObject camera = doc["cameras"];
  for (JsonObject::iterator it=camera.begin(); it!=camera.end(); ++it) {
    Log.noticeln("1 camera here");
    Serial.println(camera["channel"].as<int>());
    config.cam[it]->channel = camera["channel"].as<int>(); // lost here ;)
  }

Program output
Expected output:
(apparently I get the data right but I cannot set the structure correctly

Actual output:

1
10
@simonemarin
Copy link
Author

So I have added my own counter but isn't there a way to get the index of the current item?

  int counter = 0;
  for (JsonObject camera : doc["cameras"].as<JsonArray>()) {
    Log.noticeln("1 camera here");
    Serial.println(camera["channel"].as<int>());
    config.cam[counter].channel = camera["channel"].as<int>();
    counter++;
  }

@bblanchon
Copy link
Owner

Hi @simonemarin,

No, there is no way to get the index from the nested object.
Adding a counter, as you did, is the right solution.

Did you solve your original problem?

Best regards,
Benoit

@simonemarin
Copy link
Author

I am still failing ad adding the values from json to the structure:

struct Camera {
    char viscaip[16];
    int port;
    int channel;
    char HEXpan[8];
    char HEXtiltUp[8];
    char HEXtiltDown[8];  
};

struct Config {
    char hostip[16];
    Camera* cam[];
};

Config config;
Camera cam[10]; //seems like I HAVE to set a maximum size

StaticJsonDocument<512> doc;
DeserializationError error = deserializeJson(doc, file);
JsonObject camera = doc["cameras"];
for (JsonObject::iterator it=camera.begin(); it!=camera.end(); ++it) {
    Log.noticeln("1 camera here");
    Serial.println(camera["channel"].as<int>());
    config.cam[it]->channel = camera["channel"].as<int>(); // lost here ;)
}

readFile(SPIFFS, filename, config);

void readFile(fs::FS &fs, const char * path, Config &config) {

  File file = fs.open(path);
  if (!file) {
    Log.errorln("Failed to open file for reading");
    return;
  }

  StaticJsonDocument<1024> doc;

  // Deserialize the JSON document
  DeserializationError error = deserializeJson(doc, file);
  if (error)
    Log.errorln(F("Failed to read file, using default configuration"));

  
  for (JsonObject camera : doc["cameras"].as<JsonArray>()) {
    Log.noticeln("Json camera with channel: %d", camera["channel"].as<int>());
    config.cam[cam_counter].channel = camera["channel"].as<int>();
    cam_counter++;
  }

  for (int i = 0; i < cam_counter; i++) {
    Log.noticeln("Iteration %d, struct camera channel: %d", i, cam[i].channel);
  }
  
  Log.noticeln("Total cameras: %d", cam_counter);

}

I get :

I: Json camera with channel: 1
I: Json camera with channel: 10
I: Iteration 0, struct camera channel: 0
I: Iteration 1, struct camera channel: 0
I: Total cameras: 2

So something is wrong in the way I set the data.

@simonemarin
Copy link
Author

yay
config.cam[cam_counter].channel = camera["channel"].as<int>();
should be
cam[cam_counter].channel = camera["channel"].as<int>();
surely your book will come at hand ;)

@bblanchon
Copy link
Owner

Hi @simonemarin,

From your last message, I understand that your problem is fixed, so I'm going to close this issue.

For simple configurations files, you can look at the JsonConfigFile.ino example.
For complex configurations, look at the "Configuration in SPIFFS" case study in Mastering ArduinoJson: it shows how to leverage custom converters to support nested objects.

@simonemarin, thank you very much for purchasing my book; your support is greatly appreciated.
Let me know if you have any remarks about the book.

Best regards,
Benoit

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 5, 2022
@bblanchon bblanchon added the v6 ArduinoJson 6 label Feb 6, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
question v6 ArduinoJson 6
Projects
None yet
Development

No branches or pull requests

2 participants