kornisb
kornisb

Reputation: 260

Jackson deserialization of list, skip elements without specific field

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:

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

Answers (3)

jhon
jhon

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

Justin Jose
Justin Jose

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

Sharon Ben Asher
Sharon Ben Asher

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

Related Questions