Skip to content

readTree explodes when reading json with type information #88

@electricmonk

Description

@electricmonk

When reading json that has type information, readTree explodes on ClassCastException upon trying to assert that JsonNode is a supertype of the type in the type information. This is, of course, wrong.

As far as I can tell, the bug is in AsPropertyTypeDeserializer.deserializeTypedFromObject:

            if (_typePropertyName.equals(name)) { // gotcha!
                return _deserializeTypedForId(jp, ctxt, tb);
            }

Follows is a test that recreates the bug:

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.TextNode;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

/**
 * @author shaiyallin
 * @since 10/2/12
 */
public class DefaultTypingReadTreeBugTest {

    ObjectMapper mapper = new ObjectMapper();

    @Test
    public void valueAsStringWithoutDefaultTyping() throws Exception {

        Foo foo = new Foo("baz");
        String json = mapper.writeValueAsString(foo);

        JsonNode jsonNode = mapper.readTree(json);
        assertEquals(jsonNode.get("bar").textValue(), foo.getBar());
    }

    @Test
    public void valueAsStringWithDefaultTyping() throws Exception {
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);

        Foo foo = new Foo("baz");
        String json = mapper.writeValueAsString(foo);

        JsonNode jsonNode = mapper.readTree(json);
        assertEquals(jsonNode.get("bar").textValue(), foo.getBar());
    }

    @Test
    public void readTreeWithDefaultTyping() throws Exception {

        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        String json = "{\"@class\":\"DefaultTypingReadTreeBugTest$Foo\",\"bar\":\"baz\"}";
        JsonNode jsonNode = mapper.readTree(json);
        assertEquals(jsonNode.get("bar").textValue(), "baz");
    }

    @Test
    public void valueToTreeWithoutDefaultTyping() throws Exception {

        Foo foo = new Foo("baz");
        JsonNode jsonNode = mapper.valueToTree(foo);
        assertEquals(jsonNode.get("bar").textValue(), foo.getBar());
    }

    @Test
    public void valueToTreeWithDefaultTyping() throws Exception {
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);

        Foo foo = new Foo("baz");
        JsonNode jsonNode = mapper.valueToTree(foo);
        assertEquals(jsonNode.get("bar").textValue(), foo.getBar());
    }


    public static class Foo {
        private String bar;

        public Foo() {
        }

        public Foo(String bar) {
            this.bar = bar;
        }

        public String getBar() {
            return bar;
        }

        public void setBar(String bar) {
            this.bar = bar;
        }
    }
}

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