Skip to content

ArduinoJson v7 compatibility (keeping v6 support) - #457

Open
jeremypoulter wants to merge 1 commit into
matth-x:mainfrom
jeremypoulter:claude/arduinojson-v6-v7-compat-l0jv42
Open

jeremypoulter wants to merge 1 commit into
matth-x:mainfrom
jeremypoulter:claude/arduinojson-v6-v7-compat-l0jv42

Conversation

@jeremypoulter

Copy link
Copy Markdown

Summary

OpenEVSE's ESP32 firmware moved to ArduinoJson v7 in OpenEVSE/openevse_esp32_firmware#1044 and hit a hard compile break in MicroOcpp, currently worked around with a build-time source patch that rewrites ReserveNow.cpp after PlatformIO downloads it. This PR fixes the underlying incompatibility properly (while keeping ArduinoJson v6 working exactly as before), so that patch is no longer needed.

  • src/MicroOcpp/Operations/ReserveNow.cpp: payload["connectorId"] < 0 is a hard compile error under v7 (MemberProxy's copy constructor is private there). Fixed with .as<int>() < 0, verified byte-identical behavior under both v6 and v7.
  • src/MicroOcpp/Core/Memory.h / .cpp: the unit tests build with MO_OVERRIDE_ALLOCATION=1, and v7's BasicJsonDocument<TAllocator> requires the allocator to implement reallocate() (a virtual override that must compile even if unused, unlike v6's lazily-instantiated template method). Added reallocate() to ArduinoJsonAllocator, plus mo_mem_realloc/mo_mem_set_realloc mirroring the existing malloc/free override hooks (defaults to standard realloc() if no override is set). Also branched initJsonDoc/makeJsonDoc on ARDUINOJSON_VERSION_MAJOR, since v7's allocator is a process-wide singleton and no longer takes a per-call instance (so the memory tag is not propagated to JSON allocations specifically under v7 — a real but harmless loss of heap-profiler granularity).
  • tests/SmartCharging.cpp: *doc = raw[3] relied on an implicit conversion v7 dropped (same failure signature as Error on Make - Invalid Initialization of Reference #295, whose original file — RequestStore.cpp — no longer exists in the current tree, having been refactored away; the remaining occurrence was in this test file). Replaced with doc->set(raw[3]), identical under both versions.
  • containsKey() / DynamicJsonDocument / StaticJsonDocument (~50 files) are deliberately left as-is. They only produce deprecation warnings under v7 (not hard errors), and rewriting them to is<T>() would silently turn presence checks into type checks — the same regression class fixed in jeremypoulter/ConfigJson@9ceb24c.

CI changes

  • tests.yml and platformless.yml now matrix over a pinned ArduinoJson v6 and v7 release.
  • platformless.yml's v7 leg drops -Werror: JSON_OBJECT_SIZE/JSON_ARRAY_SIZE unconditionally emit a _Pragma("GCC warning") under v7 that no -Wno-* flag suppresses, and ~50 files call them.
  • pio.yml gets a v7 leg via a lib_deps override on both ESP32 examples.
  • esp-idf.yml is untouched — ESP-IDF v4.4 was too heavy to set up and verify locally in this session (unlike PlatformIO, whose ESP32 toolchain was available), so it's flagged as unverified rather than guessed at. It still passes CI unchanged, since it stays on the pinned pre-v7 ArduinoJson commit.

Test plan

Verified locally and confirmed by CI on a staging PR against the fork (jeremypoulter#1) before opening this one:

  • Unit tests (1192 assertions / 20 cases) pass under both ArduinoJson v6.21.3 and v7.4.3
  • Same, under valgrind (no leaks/errors) and ASan+UBSan (clean) for both versions
  • platformless.yml's all-source -Werror compile passes under both versions (dropping -Werror only for v7, as above)
  • Both PlatformIO ESP32 examples (examples/ESP, examples/ESP-TLS) build and link against ArduinoJson v7.4.3
  • CI on the staging PR: Unit tests, Default Compilation (platformless), PlatformIO CI, and ESP-IDF CI all green

🤖 Generated with Claude Code

https://claude.ai/code/session_01WcRQbbTJiPa1wZRZCaueBN

ArduinoJson v7 makes MemberProxy non-copyable, which broke the direct
relational comparison payload["connectorId"] < 0 in ReserveNow.cpp with
a hard compile error. Fix it with an explicit .as<int>() conversion,
which behaves identically under v6 and v7.

v7's BasicJsonDocument<TAllocator> wraps the allocator in a process-wide
singleton (AllocatorAdapter) instead of holding a per-instance allocator,
so it (a) has no two-argument constructor anymore - initJsonDoc/
makeJsonDoc now branch on ARDUINOJSON_VERSION_MAJOR - and (b) requires
the allocator to implement reallocate(), which ArduinoJsonAllocator
didn't have since v6 never called it. Add mo_mem_realloc/
mo_mem_set_realloc, mirroring the existing malloc/free override hooks,
and wire it up via a new MO_REALLOC macro.

*doc = raw[3] in the SmartCharging unit tests relied on an implicit
JsonDocument conversion that v7 no longer supports (the same failure
reported far upstream in issue matth-x#295, whose original file has since been
refactored away); doc->set(raw[3]) is the version-independent equivalent.

containsKey()/DynamicJsonDocument/StaticJsonDocument stay as they are:
under v7 they only produce deprecation warnings, and rewriting them to
is<T>() would silently change presence checks into type checks (see
jeremypoulter/ConfigJson@9ceb24c for what that class of regression looks
like). CI now builds and runs the unit tests, and separately compiles
all of src/ with -Werror, against both a pinned ArduinoJson v6 and v7
release. The -Werror leg drops -Werror for v7 only, because
JSON_OBJECT_SIZE/JSON_ARRAY_SIZE unconditionally emit a
_Pragma("GCC warning") in v7 that no -Wno-* flag can suppress, and left
in place across the ~50 files that call them for now.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WcRQbbTJiPa1wZRZCaueBN
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants