Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ObjectMapper's .valueToTree() wraps JsonNode objects into a POJONode #433

Closed
fge opened this issue Apr 5, 2014 · 6 comments
Closed

ObjectMapper's .valueToTree() wraps JsonNode objects into a POJONode #433

fge opened this issue Apr 5, 2014 · 6 comments
Milestone

Comments

@fge
Copy link
Contributor

fge commented Apr 5, 2014

Affected versions: 2.2.3, 2.3.2.

Let us take these two sample classes:

public final class BasicBean
{
    private String foo;

    public void setFoo(final String foo)
    {
        this.foo = foo;
    }

    public String getFoo()
    {
        return foo;
    }

    public static void main(final String... args)
    {
        final BasicBean foo = new BasicBean();
        foo.setFoo("bar");
        final ObjectMapper mapper = new ObjectMapper();
        final JsonNode node = mapper.valueToTree(foo);
        System.out.println(node.getNodeType());
        System.out.println(node);
    }
}

and this one:

public final class CustomSerializedPojo
    implements JsonSerializable
{
    private final ObjectNode node = JsonNodeFactory.instance.objectNode();

    public void setFoo(final String foo)
    {
        node.put("foo", foo);
    }

    @Override
    public void serialize(final JsonGenerator jgen,
        final SerializerProvider provider)
        throws IOException, JsonProcessingException
    {
        jgen.writeTree(node);
    }

    @Override
    public void serializeWithType(final JsonGenerator jgen,
        final SerializerProvider provider, final TypeSerializer typeSer)
        throws IOException, JsonProcessingException
    {
        typeSer.writeTypePrefixForObject(this, jgen);
        serialize(jgen, provider);
        typeSer.writeTypeSuffixForObject(this, jgen);
    }

    public static void main(final String... args)
    {
        final CustomSerializedPojo pojo = new CustomSerializedPojo();
        pojo.setFoo("bar");
        final ObjectMapper mapper = new ObjectMapper();
        final JsonNode node = mapper.valueToTree(pojo);
        System.out.println(node.getNodeType());
        if (node.getNodeType() == JsonNodeType.POJO) {
            final Object embedded = ((POJONode) node).getPojo();
            System.out.println(embedded.getClass());
            System.out.println(embedded);
        }
    }
}

The execution of the first main gives:

OBJECT
{"foo":"bar"}

However, the execution of the second one gives:

POJO
class com.fasterxml.jackson.databind.node.ObjectNode
{"foo":"bar"}

Therefore, if .valueToTree() is called on a class implementing JsonSerializable, it embeds the result of the serialization into a POJONode!

NOTE: I did check that it was the .serialize() method which was called and not .serializeWithType().

@fge
Copy link
Contributor Author

fge commented Apr 5, 2014

Uh, wait, actually it doesn't do this for all JsonSerializable classes; JsonNode and derivates are not affected, for instance...

cowtowncoder added a commit that referenced this issue Apr 5, 2014
cowtowncoder added a commit that referenced this issue Apr 5, 2014
@cowtowncoder cowtowncoder added this to the 2.3.3 milestone Apr 5, 2014
@cowtowncoder
Copy link
Member

Fixed: the problem was due to value conversion writing to TokenBuffer (which is ok so far) and JsonNodeDeserializer only seeing "some POJO": instead, needs special handling. Fixed for 2.3.3 and 2.4.0.

@cowtowncoder
Copy link
Member

Hmmh. Come to think of it now, this will only solve the case of JsonNode, but will still have problems with other JsonSerializable cases. Will create a separate issue for solving more general issue.

@cowtowncoder cowtowncoder changed the title ObjectMapper's .valueToTree() wraps JsonSerializable objects into a POJONode ObjectMapper's .valueToTree() wraps JsonNode objects into a POJONode Apr 5, 2014
@cowtowncoder
Copy link
Member

Never mind. Was too fast with commentary. It really depends on exactly how serialize() (and/or serializeWithType()) is implemented: specific issue here was that writeTree() implementation of TokenBuffer just embeds node; but then JsonNodeDeserializer not realizing it should fetch "hidden" node. So there is no generic problem, nor solution.

@fge
Copy link
Contributor Author

fge commented Apr 6, 2014

Uhm, how do I understand your last statement then?

I'd love to use that method; and I know I want JsonNodes out of it. Should I then inspect it if it is a POJONode as a workaround?

@cowtowncoder
Copy link
Member

Comment was on previous comment; but the short answer is that as far as I know, use of generator.writeTree() should now work as expected, even when using value conversion methods.

So you should not have to inspect anything: JsonNodeDeserializer should be able to figure things out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants