Lalao
Lalao

Reputation: 423

Jackson read json in generic List

I'm using Jackson in order to read json messages. One of the values that I' trying to parse is a List and another value contains the type of the data in the list. This is the structure i 've created in java.

public class Message<T> {
   private Timestamp time;
   private RestAction action;
   private String type;
   private List<T> data;
}

Through Class.forName(); I can get the class which represents the data in the list. The question is how can I read the List.

Upvotes: 40

Views: 83909

Answers (6)

Paul EDANGE
Paul EDANGE

Reputation: 220

This should work for simple POJO and Collections:

// import com.fasterxml.jackson.core.type.TypeReference;
// import com.fasterxml.jackson.databind.ObjectMapper;

// get your <T> type
final Type entryType = ...

// Create a new TypeReference object and convert
return new ObjectMapper().readValue(jsonString, new TypeReference<>() {
    @Override
    public Type getType() {
        return entryType;
    }
});

Upvotes: 0

splatch
splatch

Reputation: 1599

Something which is much shorter:

mapper.readValue(jsonString, new TypeReference<List<EntryType>>() {});

Where EntryType is a reference to type you would like to hold within collection. It might be any Java class. For example to read JSON representation such as ["a", "b", "c"] second argument to mapper should be new TypeReference<List<String>>() {}

Upvotes: 104

Malt
Malt

Reputation: 30285

Since version 2.11 (Apr 2020) Jackson has readerForListOf method (documentation):

ObjectMapper mapper = ObjectMapper().configure(...);
ObjectReader reader = mapper.readerForListOf(MyClass.class);
List<MyClass> list = reader.readValue(...);

Upvotes: 9

mahesh
mahesh

Reputation: 7

If you need to read json in generic List, Do something like

{
    Employee:
    [
        {
            "key": "value",
            "key": "value"
        },
        {
            "key": "value",
            "key": "value"
        }
    ]
} 

your json list object and your bean class is

class person {
private String key;
private String value;
}

now you can read this json using HashMap

something like

TypeReference<HashMap<String,List<Person>>> personList =  new   TypeReference<HashMap<String, List<Person>>>() {};

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

HashMap<String, List<Person>> employees = objectMapper.readValue(request.getInputStream(), personList);

Upvotes: -2

alex
alex

Reputation: 3442

If you need to map the incoming json to your List you can do like this

String jsonString = ...; //Your incoming json string
ObjectMapper mapper = new ObjectMapper();
Class<?> clz = Class.forName(yourTypeString);
JavaType type = mapper.getTypeFactory().constructCollectionType(List.class, clz);
List <T> result = mapper.readValue(jsonString, type);

Edit

Something like this, completly untested and never done

public Message<T> deserialize(JsonParser jsonParser, DeserializationContext arg1)
    throws IOException, JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    ObjectCodec oc = jsonParser.getCodec();
    JsonNode node = oc.readTree(jsonParser);

    JsonNode timeStamp = node.get("time");
    Timestamp time = mapper.readValue(timeStamp, Timestamp.class);
    JsonNode restAction = node.get("action");
    RestAction action = mapper.readValue(restAction, RestAction.class);
    String type = node.get("type").getTextValue();
    Class<?> clz = Class.forName(type);
    JsonNode list = node.get("data");
    JavaType listType = mapper.getTypeFactory().constructCollectionType(List.class,   clz);
    List <T> data = mapper.readValue(list, listType);

    Message<T> message = new Message<T>;
    message.setTime(time);
    message.setAction(action);
    message.setType(type);
    message.setData(data);

    return message;
}

Upvotes: 74

seralex.vi
seralex.vi

Reputation: 620

You need to annotate your class with @JsonDeserialize(using = MessageDeserializer.class) and implement custom deserializer:

public class MessageDeserializer extends JsonDeserializer<Message> {
  @Override
  public Message deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
    throws IOException, JsonProcessingException {
    // YOU DESERIALIZER CODE HERE
  }
}

@see examples here: How Do I Write a Jackson JSON Serializer & Deserializer?

Upvotes: 4

Related Questions