Skip to content

Deserializing JSON with missing field fails using @JsonbCreator #237

@emattheis

Description

@emattheis

When I attempt to deserialize a JSON document with missing fields as a Java type using @JsonbCreator I get the following exception:

javax.json.bind.JsonbException: JsonbCreator parameter PARAM_NAME is missing in json document.

Looking into the source, I found this which indicates that the error condition is mandated by the spec. However, I can't find anything in the spec that requires all parameters in a creator to be present. Am I missing it?

Here's a test class that illustrates the issue:

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;

import javax.json.bind.Jsonb;
import javax.json.bind.annotation.JsonbCreator;
import javax.json.bind.annotation.JsonbProperty;

import org.eclipse.yasson.internal.JsonBindingBuilder;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class JsonbCreatorTest {
    public static class Mutable {
        private String test = "default";

        public String getTest() {
            return test;
        }

        public void setTest(String test) {
            this.test = test;
        }
    }

    public static class Immutable {
        private final String test;

        @JsonbCreator
        public Immutable(@JsonbProperty("test") String test) {
            this.test = test;
        }

        public String getTest() {
            return test;
        }
    }

    private static final String OBJECT_WITH_FIELD = "{\"test\":\"test\"}";

    private static final String EMPTY_OBJECT = "{}";

    private Jsonb jsonb;

    @BeforeEach
    public void createJsonBuilder() {
        jsonb = new JsonBindingBuilder().build();
    }

    @Test
    public void testDeserializeMutableFromObjectWithField() {
    	Mutable mutable = jsonb.fromJson(OBJECT_WITH_FIELD, Mutable.class);
    	assertEquals("test", mutable.getTest());
    }

    @Test
    public void testDeserializeImmutableFromObjectWithField() {
    	Immutable immutable = jsonb.fromJson(OBJECT_WITH_FIELD, Immutable.class);
    	assertEquals("test", immutable.getTest());
    }

    @Test
    public void testDeserializeMutableFromEmptyOBject() {
    	Mutable mutable = jsonb.fromJson(EMPTY_OBJECT, Mutable.class);
    	// spec says the setter MUST NOT be called when the property is absent
    	assertEquals("default", mutable.getTest());
    }

    @Test
    public void testDeserializeImmutableFromEmptyOBject() {
    	Immutable immutable = jsonb.fromJson(EMPTY_OBJECT, Immutable.class);
    	// spec does not seem to mention how to handle this - null seems like the only sane choice
    	assertNull(immutable.getTest());
    }
}

Ultimately, I think this needs to be clarified in the spec, so I will raise it there as well, but I would like a way to get null passed in to creators when fields are missing instead of exceptions. I don't want to have to resort to mutable POJOs just to support this use case.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions