Skip to content

Deserialization of empty JsonNode fails if @JsonValue is used #346

@agavrilov76

Description

@agavrilov76

I'm not sure whether this is a defect, but I'm getting an exception when trying to de-serialize an empty "{}" object into a JsonNode when using @jsonvalue.

Please see the code below:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.io.IOException;

/**
 * Deserialization of an empty JsonNode fails if  @JsonValue is used
 */
public class JsonNodeIssue {

    @JsonDeserialize(as = JsonDataImpl.class)
    public static interface Data {
        String getString();
    }

    public static class JsonDataImpl implements Data {
        private final JsonNode jsonNode;

        @JsonCreator
        public JsonDataImpl(JsonNode jsonNode) {
            this.jsonNode = jsonNode;
        }

        @JsonValue
        public JsonNode getJsonNode() {
            return jsonNode;
        }

        @Override
        public String getString() {
            JsonNode string = jsonNode.get("string");
            return string == null ? null : string.toString();
        }
    }

    @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
    public static class DataImpl implements Data {

        final private String string;

        public DataImpl(String string) {
            this.string = string;
        }

        @Override
        public String getString() {
            return string;
        }
    }

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();

        System.out.println("Json: " + new String(mapper.writeValueAsBytes(new DataImpl("abc"))));
        System.out.println("Json2: " + new String(mapper.writeValueAsBytes(new DataImpl(null))));

        Data data = mapper.readValue("{\"string\":\"abc\"}", Data.class);
        System.out.println("string1:" + data.getString());

        // the following line fails:
        data = mapper.readValue("{}", Data.class);
        System.out.println("string2:" + data.getString());
    }
}

Here is the output:

Json: {"string":"abc"}
Json2: {}
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of com.fasterxml.jackson.databind.JsonNode out of END_OBJECT token
 at [Source: java.io.StringReader@2b94d9d5; line: 1, column: 2]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:575)
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:569)
    at com.fasterxml.jackson.databind.deser.std.BaseNodeDeserializer.deserializeAny(JsonNodeDeserializer.java:322)
    at com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer.deserialize(JsonNodeDeserializer.java:63)
    at com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer.deserialize(JsonNodeDeserializer.java:15)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:973)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:276)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
    at JsonNodeIssue.main(JsonNodeIssue.java:65)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
string1:"abc"

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