1

So I am seeking to deserialise and serialise an object using Jackson. The object has a hierarchy, and deep down in the hierachy there is a

List<T>

where T is either a String, or one of the Java number classes.

Deserialising generic lists has been a common topic on these forums, and I know how to build a mapper that will deserialise or serialise a list using mapper.readValue.

What I don't know how to do is make is so that when I call the mapper on the top level, which doesn't know explicitly about the parametrisation of the classes that it contains, such that it will know how to call the custom deserialiser when it gets to the bottom level class that contains the parameterised list.

A simple example with getters/setters/constructors ommitted:

class A {
    String name;
    B thing;
}

class B {
    String command;
    List<C<?>> conditions;
}

class C<T> {
    String type;
    List<T> parameters
}

And I want to write a Jackson command that serialises A in one go. I have been using a method attached to A:

public String toJSON() throws JsonProcessingException{
    ObjectMapper mapper = new ObjectMapper();
    mapper.enableDefaultTyping();
    return mapper.writeValueAsString(this);
}

but this has the known issue of generic collections losing their type information and not being deserialisable.

I can use the advice here to deserialise a given class with a generic parameter, but I don't see how to combine these solutions. I was hoping that Jackson has some what that I an write a custom deserialiser for C, and it can use that when it reaches that class type, and otherwise it can use the normal serialiser, which works fine for the other classes.

phil_20686
  • 4,000
  • 21
  • 38
  • try to use Gson library way better.. – Sercan Ozdemir Jun 10 '14 at 14:23
  • @sercan Show us all that objective proof you've got there. – Sotirios Delimanolis Jun 10 '14 at 14:23
  • If someone puts up a solution to this problem in Gson I will happily use it.... Off to read their user guide now. – phil_20686 Jun 10 '14 at 14:25
  • @SercanOzdemir if you suggest use of different library, the least you can do is try to explain how that would help; otherwise you are just sending OP to a wild goose hunt. – StaxMan Jun 10 '14 at 18:22
  • sorry about it but i don't have enough time to test and write it to here. But i can give you a link that tells you how to customize serialization/deserialization with GSON, here's a one of them http://www.javacreed.com/gson-serialiser-example/ – Sercan Ozdemir Jun 11 '14 at 05:41

1 Answers1

4

When Jackson is deserializing your JSON into an object of type A, it sees the following when deserializing for its B field

List<C<?>> conditions;

Neither you (the programmer), nor Jackson know what type C's parameters field should have. As such, it doesn't have enough information to deserialize like you would want it. Instead, it will use its default type which I believe is a LinkedHashMap (or something similar).

Basically, your only option is to give it hints. (Custom) Serialize the object hierarchy with a String value of the Class to deserialize to. You can then have a different strategy for each of those types in your custom deserializer.

Since you only have a few types, String or one of the Number classes, you might be better served writing a generic class C and X non generic classes for each of the types

class C<T> {}
class StringC extends C<String> {}
class IntegerC extends C<Integer> {}

and use some polymorphic type handling to serialize/deserialize.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • This worked a treat. It was quick and easy and required almost no extra work. :) – phil_20686 Jun 11 '14 at 13:47
  • 1
    Yes, its a linked hashmap, and I wasted a whole day figuring out from where this LinkedHashMap casting error to my actual generic type is coming from. – rohanagarwal Dec 28 '18 at 13:01