Leon
Leon

Reputation: 3244

How to de/serialize List<Object> with Jackson?

How to serialize/deserialize a List of objects like below with Jackson?

List<Object> items = new ArrayList<Object>();
items.add(1);           //integer
items.add(1.23);        //float
items.add("abc");       //string
items.add(Color.RED);   //enum
items.add(new Date());  //date

The possible item classes are integer, float, string, enum and date. The base class of the items is object so there is no chance to specify @JsonTypeInfo.

The desired output should be like output of @JsonTypeInfo, e.g.,

[
{"java.lang.Integer": 1},
{"java.lang.Float": 1.23},
{"java.lang.String": "abc"},
{"mypackage.Color": "RED"},
{"java.util.Date","2000-01-01T00:00:00+0000"}
]

Or

[
    {type:"java.lang.Integer",value: 1},
    {type:"java.lang.Float",value: 1.23},
    ...
]

Maybe I need a MixIn to customize this myself?

Upvotes: 1

Views: 4642

Answers (1)

Bnrdo
Bnrdo

Reputation: 5474

You cannot do that with JsonTypeInfo. You need a custom serializer that checks the instance of each items in the list and serialize them accordingly.

First, create a wrapper of your list.

@JsonSerialize(using = MyCustomListSerializer.class)
public class ListWrapper {
    private List<Object> list;

    public ListWrapper(){
        list = new ArrayList<>();
    }

    public void add(Object o){
        list.add(o);
    }

    public Object get(int i){
        return list.get(i);
    }

    public List<Object> list(){
        return list;
    }
}

Then the custom serializer

public class MyCustomListSerializer extends JsonSerializer<ListWrapper> {
    @Override
    public void serialize(ListWrapper value, JsonGenerator jgen, SerializerProvider provider)
      throws IOException, JsonProcessingException {

        jgen.writeStartArray();

        for(Object o : value.list()){
            jgen.writeStartObject();
            if(o instanceof Integer){
                jgen.writeNumberField("java.lang.Integer", (int) o);
            }else if(o instanceof Double){ //by default, floated values are represented by double
                jgen.writeNumberField("java.lang.Float", (double) o);
            }else if(o instanceof Color){
                jgen.writeStringField("myPackage.Color", ((Color)o).toString());
            }else if(o instanceof Date){
                jgen.writeStringField("java.util.Date", o.toString());
            }else{ //default to String
                jgen.writeStringField("java.lang.String", o.toString());
            }
            jgen.writeEndObject();
        }

        jgen.writeEndArray();
    }
}

Upvotes: 4

Related Questions