Dmitry  Adonin
Dmitry Adonin

Reputation: 1204

Deserialize list of objects with inner list with Jackson

I have such an entity:

public class User {

    private Long id;
    private String email;
    private String password;
    private List<Role> roles;

    //set of constructors, getters, setters...

and related JSON:

[
  {
    "email": "user@email",
    "roles": ["REGISTERED_USER"]
  }
]

I'm trying to deserialize it in Spring MVC @Controller in such way:

List<User> users = Arrays.asList(objectMapper.readValue(multipartFile.getBytes(), User[].class));

Before adding List<Role> it worked perfect, but after I still have no luck. It seems I need some custom deserializer, could you help with approach for solving? Thank you!

Upvotes: 4

Views: 10230

Answers (1)

varren
varren

Reputation: 14731

If you have access to Role class you can just add such constructor:

private Role(String role) {
   this.role = role;
}

or static factory methods:

@JsonCreator
public static Role fromJson(String value){
    Role role = new Role();
    role.setRole(value);
    return role;
}

@JsonValue
public String toJson() {
    return role;
}

Otherwise you will have to write custom deserealizer and register it on object mapper like this:

public static class RoleSerializer extends JsonSerializer {
    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
        gen.writeString(((Role) value).getRole());
    }
}

public static class RoleDeserializer extends JsonDeserializer {
    @Override
    public Role deserialize(JsonParser jsonParser,DeserializationContext deserializationContext) throws IOException {
        ObjectCodec oc = jsonParser.getCodec();
        JsonNode node = oc.readTree(jsonParser);
        Role role =  new Role();
        role.setRole(node.asText());
        return role;
    }
}

Here is demo: https://gist.github.com/varren/84ce830d07932b6a9c18

FROM: [{"email": "user@email","roles": ["REGISTERED_USER"]}]

TO OBJ: [User{id=null, email='user@email', password='null', roles=Role{role='REGISTERED_USER'}}]

TO JSON:[{"email":"user@email","roles":["REGISTERED_USER"]}]

Ps: If you use ObjectMapper like this

Arrays.asList(objectMapper.readValue(multipartFile.getBytes(), User[].class));

then code from demo will work, but you will probably have to set custom Bean in Spring for jackson ObjectMapper to make RoleDeserializer and RoleSerializer work everywhere. Here is more info: Spring, Jackson and Customization (e.g. CustomDeserializer)

Upvotes: 4

Related Questions