How to deserialize a parent class with a custom deserializer

1,270 views
Skip to first unread message

James Pinkerton

unread,
Jan 18, 2016, 4:26:24 PM1/18/16
to jackson-user
Hello! I'd like to deserialize a java class:

class A.

I want to use @JsonDeserialize(using AFactory.class).

I also have a class B extends A.

In AFactory I'd like to provide the deserialize(JsonParser jp, DeserializationContext ctxt) method.

I want it to do some pre-processing (why I don't use @JsonTypeInfo) and then return an instance of B (or whichever class that extends A I choose).

When I at the end do 

        JsonNode node = jp.getCodec().readTree(jp);
        String clazzNode = node.get("class").asText();
        clazz = (Class<? extends Topological>) Class.forName(clazzname); //This is B.
        return (Topological) jacksonMapper.treeToValue(node, clazz);

I get an infinite loop because the jacksonMapper.treeToValue() tries to re-run the same pre-processor, even though I told it to do clazz, which is B, not A!

How should I do this correctly?

Tatu Saloranta

unread,
Jan 18, 2016, 4:53:38 PM1/18/16
to jackson-user
There are couple of ways to avoid this, but essentially the problem here is that sub-class also has the "same" @JsonDeserialize annotation as parent class -- annotations inherit (from Jackson perspective).
One possibility to avoid that would be add explicit @JsonDeserialize in sub-class, leave out 'using'; that will leave "not defined".

-+ Tatu +-


--
You received this message because you are subscribed to the Google Groups "jackson-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jackson-user...@googlegroups.com.
To post to this group, send email to jackso...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

James Pinkerton

unread,
Jan 18, 2016, 6:06:38 PM1/18/16
to jackson-user
Great Idea!

I have this system of:

@JsonDeserialize(using=AFactory.class)
abstract class A

@JsonDeserialize
abstract class B extends A

class C1 extends B
class C2 extends B
class C3 extends B
...

When I do this I get the error:

problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information

Does this mean in this solution I need to do @JsonDeserialize for every Ci?

James

James Pinkerton

unread,
Jan 18, 2016, 6:18:18 PM1/18/16
to jackson-user
Also, is there a way to turn off inheritance?

James

Tatu Saloranta

unread,
Jan 19, 2016, 1:36:18 PM1/19/16
to jackso...@googlegroups.com
At this point there is no way to turn off inheritance, either for specific type, or more generally. I would be interested in ideas of how this could be achiever, if possible, but so that code that handles this would not be tied to specific annotation types (that is, code would need to have special cases for special annotations -- right now it is very generic and relatively simple).

As to abstract type... yeah, default BeanDeserializer can not instantiate abstract types. How would you deserializer it manually? If there is a concrete implementation, you could still use

@JsonDeserialize(as=ImplementationType.class)

(or, register abstract-to-concrete mapping using SimpleModule)

-+ Tatu +-

Reply all
Reply to author
Forward
0 new messages