Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • A ArduinoJson
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 24
    • Issues 24
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 0
    • Merge requests 0
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Benoît Blanchon
  • ArduinoJson
  • Issues
  • #1572
Closed
Open
Issue created May 24, 2021 by Administrator@rootContributor

`serializeJson()` continues appending to `String` when allocation fails

Created by: softplus

I'm using deserializeJson / serializeJson to receive, store, send data and noticed weird behavior for "longish" inputs. My guess is something is being incorrectly buffered and overwriting itself, leading to invalid serialized JSON output.

This is on Arduino 1.8.13, using ArduinoJson 6.18.0, compiling for ATmega32U4 on Mac OSX 11.3.1

Code:

#include <ArduinoJson.h>

void setup() {
  Serial.begin(115200); delay(2000);

  DynamicJsonDocument doc(1000);

  //String s = "{\"cmd\":\"set\",\"ver\":2,\"key\":[{\"p\":2,\"t\":1,\"k\":[\"textsingleoh boy\",\"textdouble\"]},{\"p\":3,\"t\":2,\"k\":[\"2extsingle\",\"2extdouble\"]}],\"led\":[{\"p\":4,\"t\":1,\"c\":{\"p\":1,\"v\":2,\"i\":255,\"d\":10},\"s\":[2]}]}"; // fails
  String s = "{\"cmd\":\"set\",\"ver\":2,\"key\":[{\"p\":2,\"t\":1,\"k\":[\"textsingleoh boy\",\"textdouble\"]},{\"p\":3,\"t\":2,\"k\":[\"2extsingle\",\"2extdouble\"]}],\"led\":[{\"p\":4,\"t\":1,\"c\":{\"p\":1,\"v\":2,\"i\":255,\"d\":10},\"s\":20}]}"; // fails
  //String s = "{\"cmd\":\"set\",\"ver\":2,\"key\":[{\"p\":2,\"t\":1,\"k\":[\"textsingleoh boy\",\"textdouble\"]},{\"p\":3,\"t\":2,\"k\":[\"2extsingle\",\"2extdouble\"]}],\"led\":[{\"p\":4,\"t\":1,\"c\":{\"p\":1,\"v\":2,\"i\":255,\"d\":10},\"s\":2}]}"; // ok
  //String s = "{\"cmd\":\"set\",\"ver\":2,\"key\":[{\"p\":2,\"t\":1,\"k\":[\"textsingleoh boy\",\"textdouble\"]},{\"p\":3,\"t\":2,\"k\":[\"2extsingle\",\"2extdouble\"]}],\"led\":[{\"p\":4,\"t\":1,\"c\":{\"p\":1,\"v\":2,\"i\":255,\"d\":10}]}"; //ok
  //String s = "{\"cmd\":\"set\",\"ver\":2,\"key\":[{\"p\":2,\"t\":1,\"k\":[\"textsingleoh boy\",\"textdouble\"]},{\"p\":3,\"t\":2,\"k\":[\"2extsingle\",\"2extdouble\"]}]}"; // ok

  Serial.println("Deserializing: ");
  Serial.print("input ="); Serial.println(s);
  Serial.print("len="); Serial.println(s.length()); /* Serial.println(strlen(s)); */ 
  DeserializationError error = deserializeJson(doc, s);
  Serial.print("error="); Serial.println(error.c_str());
  int input_length = s.length();

  // Serialize again
  String result;
  Serial.println("Serializing: ");
  int bytes = serializeJson(doc, result);
  Serial.print("bytes="); Serial.println(bytes);
  Serial.print("result="); Serial.println(result);
  Serial.print("len="); Serial.println(result.length());

  int output_length = result.length();
  if (input_length == output_length) { Serial.println("PASS"); } else { Serial.println("FAIL"); }
}

void loop() { }

Uncommenting / commenting a line with "fails" fails, one with "ok" works. Longer ones all fail. The difference seems to be in string length, since changing an int parameter from "2" to "20" triggers the same behavior (data size should be the same). serializeJson returns the correct number of bytes, but the output string is shorter, and sometimes invalid JSON.

Sample output:

10:05:48.591 -> Deserializing: 
10:05:48.591 -> input ={"cmd":"set","ver":2,"key":[{"p":2,"t":1,"k":["textsingleoh boy","textdouble"]},{"p":3,"t":2,"k":["2extsingle","2extdouble"]}],"led":[{"p":4,"t":1,"c":{"p":1,"v":2,"i":255,"d":10},"s":20}]}
10:05:48.591 -> len=189
10:05:48.591 -> error=Ok
10:05:48.591 -> Serializing: 
10:05:48.591 -> bytes=189
10:05:48.591 -> result={"cmd":"set","ver":2,"key":[{"p":2,"t":1,"k":["textsingleoh boy","textdouble"]},{"p":3,"t":2,"k":["2extsingle","2extdouble"]}],"led":[{"p":4,"t":1,"c":{"p"}]}
10:05:48.591 -> len=158
10:05:48.591 -> FAIL
...
10:06:23.389 -> Deserializing: 
10:06:23.389 -> input ={"cmd":"set","ver":2,"key":[{"p":2,"t":1,"k":["textsingleoh boy","textdouble"]},{"p":3,"t":2,"k":["2extsingle","2extdouble"]}],"led":[{"p":4,"t":1,"c":{"p":1,"v":2,"i":255,"d":10},"s":2}]}
10:06:23.389 -> len=188
10:06:23.389 -> error=Ok
10:06:23.389 -> Serializing: 
10:06:23.389 -> bytes=188
10:06:23.389 -> result={"cmd":"set","ver":2,"key":[{"p":2,"t":1,"k":["textsingleoh boy","textdouble"]},{"p":3,"t":2,"k":["2extsingle","2extdouble"]}],"led":[{"p":4,"t":1,"c":{"p":1,"v":2,"i":255,"d":10},"s":2}]}
10:06:23.389 -> len=188
10:06:23.389 -> PASS
Assignee
Assign to
Time tracking