Reputation: 260
I would like to deserialize a JSON with Jackson to a List<User>
like
class Users {
private List<User> users;
}
class User {
private Integer id;
private String name;
}
I would like:
id
to be a mandatory field, so if a user element does not contain an id, it should be skippedname
fied to be optional, so if a user element does not contain a name it should be included to the list with null
name (or even with a Java 8 Optional value if possible)So for example in the following JSON
{
"users" : [{
"id" : 123,
"name" : "Andrew"
}, {
"name" : "Bob"
}, {
"id" : 789
},
...
]
}
the second user should be skipped during deserialization, the third one should be included in the list with empty name. Is it possible using Jackson?
Upvotes: 2
Views: 2523
Reputation: 13
You can do this with com.fasterxml.jackson.annotation .
Somthing like this :) :
public static void main(String[] args) {
String json = "{ \"users\" : [{\"id\" : 123, \"name\" : \"Andrew\"}, {\"name\" : \"Bob\"}, {\"id\" : 789}]}";
try {
ObjectMapper mapper = new ObjectMapper();
Users users = mapper.readValue(json, Users.class);
String jsonInString= mapper.writeValueAsString(selectUsers(users.getUsers()));
System.out.println(jsonInString);
} catch (Exception e) {
e.printStackTrace();
}
}
private static Collection<User> selectUsers(List<User> users) {
return org.apache.commons.collections4.CollectionUtils.select(users, new org.apache.commons.collections4.Predicate<User>() {
@Override
public boolean evaluate(User user) {
return user.getId() != null;
}
});
}
public static class Users implements Serializable {
private List<User> users;
/**
* @return the users
*/
public List<User> getUsers() {
return users;
}
/**
* @param users the users to set
*/
public void setUsers(List<User> users) {
this.users = users;
}
}
@JsonIgnoreProperties(ignoreUnknown = true)
public static class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 4223240034979295550L;
@JsonInclude(JsonInclude.Include.NON_NULL)
public Integer id;
@NotNull
public String name;
/**
* @return the id
*/
public Integer getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Integer id) {
this.id = id;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
}
Output :[{"id":123,"name":"Andrew"},{"id":789,"name":null}]
Upvotes: 0
Reputation: 2171
I think a custom deserializer can do the task as shown below.
public class UserListDeserializer extends JsonDeserializer<List<User>> {
@Override
public List<User> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonNode node = p.readValueAsTree();
Iterator<JsonNode> it = node.elements();
List<User> userList=new ArrayList<>();
while (it.hasNext()) {
JsonNode user = it.next();
if (user.get("id") != null) {
User userObj = new User();
userObj.setId(user.get("id").intValue());
userObj.setName(user.get("name")!=null?user.get("name").textValue():null);
userList.add(userObj);
}
}
return userList;
}
}
and annotate your Users class as shown below.
public class Users {
@JsonDeserialize(using=UserListDeserializer.class)
private List<User> users;
}
Upvotes: 3
Reputation: 14328
You can filter the unwanted items in the setter:
public void setUsers(List<User> users) {
this.users = users.stream().filter(u -> u != null && u.id != null).collect(Collectors.toList());
}
Here is my complete test class:
public static void main(String[] args)
{
String json = "{ \"users\" : [{\"id\" : 123, \"name\" : \"Andrew\"}, {\"name\" : \"Bob\"}, {\"id\" : 789}]}";
try {
ObjectMapper mapper = new ObjectMapper();
Users users = mapper.readValue(json, Users.class);
System.out.println(users.users);
} catch (Exception e) {
e.printStackTrace();
}
}
public static class Users
{
private List<User> users;
public void setUsers(List<User> users)
{
this.users = users.stream().filter(u -> u != null && u.id != null).collect(Collectors.toList());
}
}
public static class User
{
public Integer id;
public String name;
@Override
public String toString()
{
return"{id=" + id + ", name=" + name + "}";
}
}
output:
[{id=123, name=Andrew}, {id=789, name=null}]
Upvotes: -1