Skip to content

NativeJsonInput: treat object fields with undefined value as missing #848

Description

@pkurcx

Problem

NativeJsonInput (scala-commons, com.avsystem.commons.serialization.nativejs) only treats a missing key in a js.Dictionary / js.Object as "no value". A key that is present but set to undefined is reported as a real
field, which then fails to decode — typically with a ReadFailure — instead of being treated as absent.

This is surprising in a JS context: in JavaScript, { foo: undefined } and {} are effectively equivalent for property reads (obj.foo === undefined in both cases), and many JS-side producers emit undefined for optional
fields rather than omitting the key. As a result, payloads that round-trip through JS code (browser state, js.Dictionary built incrementally, libraries that set obj.foo = undefined for "no value") break deserialization
for fields that should be optional / have defaults.

Reproduction

val dict = js.Dictionary[js.Any]("foo" -> js.undefined)
val input = new NativeJsonInput(dict.asInstanceOf[js.Any], NativeFormatOptions())
GenCodec.read[CaseClassWithOptionalFoo](input) // fails on "foo"

vs. the working case:

val dict = js.Dictionary[js.Any]() // "foo" not set at all
// reads fine — `foo` falls back to default / Opt.Empty

Expected

NativeJsonInput should treat field: undefined the same as a missing field:

  1. ObjectInput.hasNext / nextField should skip entries whose value is js.isUndefined.
  2. ObjectInput.peekField(name) should return Opt.Empty when the key is present but its value is undefined, in addition to the key-not-present case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions