writeonce/tests/corpus/run/json-bool-fidelity/fixture.wo
shoney.arickathil f282451867 feat(json): Bool encodes true/false; fraction/exponent decode fails honestly
Closes json's two documented fidelity limits (iteration 5 strictness):

- field_class gains WOB_FIELD_BOOL (a plain `Bool` field) and
  WOB_FIELD_NIL_BOOL (a `?Bool`: WO_NIL_SCALAR nil + bool encoding) — the
  kind byte alone cannot tell a Bool slot from an Int slot, so the metadata
  carries it. Emitter writes them (field_class_meta); loader whitelists
  them; json.c encodes `true`/`false` (and `null` for a ?Bool nil), decode's
  null/omitted-key pre-write covers NIL_BOOL.
- A JSON number with a fraction or exponent is MALFORMED for an Int field:
  the checked decode (`json.decode(t) as T`) yields nil for the whole
  document instead of silently truncating 3.7 to 3 — the language has no
  float, and corrupting data quietly was the one thing a "checked decode"
  must never do. Floats stay representable through a raw `json.Value` field.
- corpus: run/json-bool-fidelity pins the round-trip (true/false both ways,
  ?Bool null both ways, fraction AND exponent rejected).
- Board's two known-gap entries struck; format doc's field_class marker list
  extended.

Verified: oop-e2e 87/0; runtime test + test-iso OK; woc-test 540/0;
log-watcher 7/0; employee 8/0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 18:04:15 +02:00

25 lines
944 B
Text

-- json fidelity (iteration 5 strictness): a Bool field encodes true/false
-- (WOB_FIELD_BOOL / WOB_FIELD_NIL_BOOL in field_class — the kind byte alone
-- cannot tell Bool from Int), a ?Bool nil is null both ways, and a JSON
-- number with a fraction or exponent is MALFORMED for an Int field: the
-- checked decode yields nil instead of silently truncating.
use json
class Flags {
on: Bool
maybe: ?Bool
n: Int
}
fn main() -> Int {
print(json.encode(Flags { on: true, maybe: nil, n: 7 }));
let back = json.decode("{\"on\":false,\"maybe\":true,\"n\":9}") as Flags;
if back != nil {
print(json.encode(Flags { on: back.on, maybe: back.maybe, n: back.n }));
}
let frac = json.decode("{\"on\":true,\"maybe\":null,\"n\":3.7}") as Flags;
if frac == nil { print("fraction rejected"); }
let expo = json.decode("{\"on\":true,\"maybe\":null,\"n\":2e3}") as Flags;
if expo == nil { print("exponent rejected"); }
return 0;
}