Add JSON support for Erlang and Elixir#2247
Conversation
PR #2247 Review — Add JSON support for Erlang and ElixirCommits reviewed: Overall: Well-structured PR with comprehensive test coverage (JSONTestSuite corpus + API tests + round-trips). The implementation is clean and the 🔴 Must-Fix1. Streaming decoder finalizes numbers prematurely
Problem: If a stream splits Also, File: %% Current code — numbers at buffer end are finalized immediately,
%% and end_of_input always errors:
decode_start(Bin, Acc, Decoders) ->
Cbs = make_callbacks(Decoders),
try
Bin1 = skip_whitespace(Bin),
parse_value(Bin1, Acc, Cbs)
catch
error:unexpected_end ->
{continue, {Bin, Acc, Cbs}}
end.
decode_continue(end_of_input, {_Buf, _Acc, _Cbs}) ->
error(unexpected_end);
decode_continue(NewData, {Buf, Acc, Cbs}) ->
Combined = <<Buf/binary, NewData/binary>>,
try
Bin1 = skip_whitespace(Combined),
parse_value(Bin1, Acc, Cbs)
catch
error:unexpected_end ->
{continue, {Combined, Acc, Cbs}}
end.Expected OTP behavior: %% OTP: number at buffer end is ambiguous
{continue, S} = json:decode_start(<<"1">>, ok, #{}),
%% More digits arrive — number becomes 12
{12, ok, <<>>} = json:decode_continue(<<"2">>, S),
%% OTP: end_of_input finalizes pending numbers
{continue, S2} = json:decode_start(<<"42">>, ok, #{}),
{42, ok, <<>>} = json:decode_continue(end_of_input, S2).Suggested approach: The number parser needs to raise 2. Malformed
|
6112795 to
2dea4f1
Compare
|
usual caveats, but looking good! PR Review: JSON Module (3 commits)Commits reviewed:
Verdict: Strong addition. Close but not fully OTP-compatible yet — 3 issues should be fixed before claiming OTP compatibility. 🔴 High Priority1.
|
Pure Erlang JSON encoder/decoder, API-compatible with OTP's json module. Supports decode/1, decode/3 with custom callbacks, and streaming via decode_start/decode_continue. Encoder handles maps, key-value lists, and checked variants for duplicate key detection. Tests combine the JSONTestSuite corpus (valid, invalid, and implementation-defined cases) with Erlang-specific API tests covering custom decoders, streaming, round-trips, key-value list encoding, and error handling. Two JSONTestSuite entries (n_structure_100000_opening_arrays and n_structure_open_array_object) are excluded because their ~634 KB of embedded test data would exhaust AtomVM memory. Signed-off-by: Davide Bettio <davide@uninstall.it>
Needed by the Elixir JSON module which uses Keyword.put_new to set the default null decoder. Signed-off-by: Davide Bettio <davide@uninstall.it>
Elixir JSON encoder/decoder adapted from upstream Elixir (commit 03b9fde6), built on top of the Erlang json module. Removed from upstream: - Protocol deriving macro (not supported on AtomVM) - Duration, Date, Time, NaiveDateTime, DateTime encoders (Calendar modules not available) - Error offset extraction from __STACKTRACE__ error_info Upstream Elixir defines the protocol, all implementations, and the main module in a single json.ex. The existing build system compiles each .ex file independently, so protocol implementations would race their protocol definition in parallel builds. Add a compile_multi macro to BuildElixir.cmake that compiles one .ex source and declares all its .beam outputs. Add EXTRA_BEAMS keyword to pack_archive so the extra beams are included in the archive. Signed-off-by: Davide Bettio <davide@uninstall.it>
json_encoder was ancient code from 2018, that didn't even support maps, since AtomVM has support for json official API, it was time to remove it. Signed-off-by: Davide Bettio <davide@uninstall.it>
Add JSON encoding and decoding to both estdlib (Erlang) and
exavmlib (Elixir), fully conforming to RFC 8259.
Erlang
jsonmodule:jsonmoduleplus Erlang-specific API tests covering custom decoders, streaming,
round-trips, and error handling
format/1,2,3and related pretty-printing functions are notimplemented
Elixir
JSONmodule:the Erlang
jsonmoduleJSON.Encoderprotocol with implementations forAtom,BitString,Integer,Float,List, andMapCalendar-based encoders(not available on AtomVM)
Also adds
Keyword.put_new/3to exavmlib, needed by the ElixirJSON decoder.
Add
compile_multimacro toBuildElixir.cmakeandEXTRA_BEAMSkeyword to
pack_archivefor compiling multi-module.exsources.This PR also remove the ancient
json_encoder.These changes are made under both the "Apache 2.0" and the
"GNU Lesser General Public License 2.1 or later" license terms
(dual license).
SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later