Skip to content

fix: non-finite floats in JSON I/O under JSON.jl v1 - #20

Merged
jmcclena merged 3 commits into
masterfrom
refac/json_v1
Jun 22, 2026
Merged

jmcclena merged 3 commits into
masterfrom
refac/json_v1

Conversation

@mgyoo86

@mgyoo86 mgyoo86 commented Jun 13, 2026 •

Copy link
Copy Markdown
Member

Once an environment resolves JSON.jl v1 (compat widened in #19), SimulationParameters breaks: v1 is strict RFC 8259 by default, so jstr2par throws on the NaN/Infinity/-Infinity tokens that IMASdd environments write (the FUSE act_json CI failures), and par2jstr throws when writing non-finite values.

The existing JSON test only round-tripped finite values, so this went uncaught.

  • jstr2par: JSON.parse(...; allownan=true) — v0.21's default, required on v1
  • par2jstr: on v1 use JSON.json(data; pretty=indent, allownan=true) (the json(data, indent) compat method silently drops kwargs); v0.21 path unchanged
  • string_decode_value: coerce scalar floats to declared Integer types — v1's allownan=true parses all numbers as Float64 by design (Parsing result of numbers depends on allownan JuliaIO/JSON.jl#397), so Entry{Int} round-trips came back as 101.0
  • new test/test_json.jl covers non-finite parse/write/file round-trip and integer round-trip; full suite green on both JSON v0.21.4 and v1.6.1 (Julia 1.11.9)

mgyoo86 added 3 commits June 12, 2026 17:04
…nd v1

JSON.jl v1 defaults to strict RFC 8259: JSON.parse throws on NaN/Infinity/
-Infinity tokens and JSON.json throws when writing non-finite floats,
whereas v0.21 parsed those tokens by default and wrote them as null.
This broke FUSE act_json/ini_json tests once the ecosystem resolved JSON v1,
because IMASdd environments write parameters JSON containing bare NaN tokens
(via its AbstractFloat lowering) that jstr2par could no longer parse.

- jstr2par: pass allownan=true to JSON.parse (no-op on v0.21, required on v1)
  so IMAS-convention non-finite tokens parse on both JSON versions
- par2jstr: under JSON v1 call JSON.json(data; pretty=indent, allownan=true)
  since the pre-1.0 compat method JSON.json(data, indent) silently drops
  keyword arguments and throws on non-finite floats; v0.21 keeps its legacy
  behavior (non-finite -> null)
- add test/test_json.jl covering token parsing, non-finite write/roundtrip,
  and file I/O on both JSON versions
JSON v1 with allownan=true parses all numbers as Float64 by design
(JuliaIO/JSON.jl#397), so Entry{Int} values came back as e.g. 101.0 and
setproperty! threw (FUSE ini_json/act_json failures). string_decode_value
now coerces scalar floats to the parameter's declared Integer type.
JSON v1 with allownan=true parses every number as Float64 (JuliaIO/JSON.jl#397). The previous fix only coerced Entry{Integer} scalars, so Float32 fields and Union eltypes like Entry{Union{Int64,Vector}} (e.g. act.ActorCoreRadHeatFlux.levels) still threw MethodError on load. string_decode_value now coerces a scalar number to the lone Real member of the declared type, and the vector branch uses convert.(etp, value) so untyped Vector members (eltype Any) no longer hit the missing Any(x) constructor.

Adds regression tests covering Int, Float32, and Union{Int,Vector} (scalar and vector) round-trips, mirroring FUSE's ini_json/act_json pattern.
@jmcclena
jmcclena merged commit f68862c into master Jun 22, 2026
2 checks passed
@mgyoo86
mgyoo86 deleted the refac/json_v1 branch June 22, 2026 20:56
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