【问题标题】:Jackson data-bind deserialization: Skip over an element dependent on a value杰克逊数据绑定反序列化:跳过依赖于值的元素
【发布时间】:2015-02-16 06:57:32
【问题描述】:

我正在使用 jackson 库来反序列化 json 数据。 如果属性不符合条件,有没有办法跳过某些元素?

举例

Java 类:

@JsonIgnoreProperties(ignoreUnknown = true)
public class Group
{
   private String name;
   private int id;
   private List<User> userList;
}

@JsonIgnoreProperties(ignoreUnknown = true)
public class User
{
   private String firstName;
   private String lastName;
   private boolean deleted;
}

Json 文件:

["test.Group", {
    "name" : "testgroup1",
    "id" : 3
    "userList" : [ "java.util.ArrayList", [ 
       ["test.User", {
        "firstName" : "John",
        "lastName"  :  "Doe",
        "deleted"  :  false } ],
       ["test.User", {
        "firstName" : "John",
        "lastName"  :  "Doe",
        "deleted"  :  true } ],
       ["test.User", {
        "firstName" : "John",
        "lastName"  :  "Doe",
        "deleted"  :  false } ] ] ]
}]

通常我是这样反序列化的:

ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
test.Group g1 = mapper.readValue(jsonString,test.Group.class);

现在,是否可以跳过属性“deleted”的值为 true 的每个用户元素? 我有办法通过数据绑定来做到这一点,还是必须使用另一种方法,如树或流式传输?

编辑

我正在为安卓而不是桌面开发。 这个问题的原因是,可能有数千个 User 元素,我想尽量减少内存使用。

【问题讨论】:

    标签: java android json jackson


    【解决方案1】:

    不跳过,而是在使用 Java 8 阅读后删除(假设您的 User 有一个用于 deleted 的 getter):

    g1.getUserList().removeIf(User::isDeleted);
    

    【讨论】:

    • 不幸的是,这不是一个选项。这是在 android 上完成的,因此不在 java 8 中。这个问题的原因是,可能有成千上万的用户,我想限制内存使用。我将编辑我的问题。
    【解决方案2】:

    您可以通过解析树节点然后过滤节点来注入中介。一个例子:

    public static void main(String[] args) 
    {
    
        Group g = new Group();
        g.setId(1);
        g.setName("Test");
    
        User u1 = new User();
        u1.setDeleted(false);
        u1.setFirstName("John");
        u1.setLastName("Jones");
    
        User u2 = new User();
        u2.setDeleted(true);
        u2.setFirstName("Jane");
        u2.setLastName("Jones");
    
        g.addUser(u1);
        g.addUser(u2);
    
        try
        {
            ObjectMapper mapper = new ObjectMapper();
            String jsonVal = mapper.writeValueAsString(g);
            JsonNode node = mapper.readTree(jsonVal);
    
            for (Iterator<Entry<String, JsonNode>> it = node.fields(); it.hasNext(); ) 
            {
                Map.Entry<String, JsonNode> field = it.next();
                String key = field.getKey();
    
                if ("userList".equals(key))
                {                   
                    JsonNode users = field.getValue();
    
                    if (users.isArray())
                    {
                        for (Iterator<JsonNode> x = users.iterator(); x.hasNext();)
                        {
                            JsonNode entry = x.next();
                            if (entry.get("deleted").asBoolean())
                            {
                                System.out.println("Remove " + entry.get("firstName").asText() + " " + entry.get("lastName").asText());
                                x.remove();
                            }
                            else
                            {
                                System.out.println("Don't remove " + entry.get("firstName").asText() + " " + entry.get("lastName").asText());
                            }
                        }
                    }
                }
            }
    
            Group grp = mapper.treeToValue(node, Group.class);
            System.out.println("Final group: " + grp);
        }
        catch (Exception e)
        {
            System.out.println("Something went wrong...");
            e.printStackTrace();
        }
    }
    

    输出结果:

    Don't remove John Jones
    Remove Jane Jones
    Final group: Group [name=Test, id=1, userList=[User [firstName=John, lastName=Jones, deleted=false]]]
    

    这是在 Group 对象上使用自定义反序列化器的第二种方法。这只是我阅读的内容,因此可能会增加效率:

    public class Answer28536024 {
    
    @JsonDeserialize(using = GroupDeserializer.class)
    public static class Group
    {
       private String name;
       private int id;
       private List<User> userList;
    
       public Group()
       {
           userList = new ArrayList<User>();
       }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public void addUser(User u)
        {
            userList.add(u);
        }
    
        public List<User> getUserList() {
            return userList;
        }
    
        public void setUserList(List<User> userList) {
            this.userList = userList;
        }
    
        @Override
        public String toString() {
            return "Group [name=" + name + ", id=" + id + ", userList=" + userList
                    + "]";
        }      
    }
    
    public static class GroupDeserializer extends JsonDeserializer<Group>
    {
    
        @Override
        public Group deserialize(JsonParser jp, DeserializationContext ctxt)
                throws IOException, JsonProcessingException {
            JsonNode node = jp.getCodec().readTree(jp);
    
            Group group = new Group();
            group.setName(node.get("name").asText());
            group.setId(node.get("id").asInt());
    
    
            JsonNode users = node.get("userList");
            if (users.isArray())
            {
                for (JsonNode userNode : users)
                {
                    if (!userNode.get("deleted").asBoolean())
                    {
                        User user = new User();
                        user.setFirstName(userNode.get("firstName").asText());
                        user.setLastName(userNode.get("lastName").asText());
                        user.setDeleted(false);
    
                        group.addUser(user);
                    }
                }
            }
    
            return group;
        }       
    }
    
    
    public static class User
    {
       private String firstName;
       private String lastName;
       private boolean deleted;
    
       public User()
       {
    
       }
    
        public String getFirstName() {
            return firstName;
        }
    
        public void setFirstName(String firstName) {
            this.firstName = firstName;
        }
    
        public String getLastName() {
            return lastName;
        }
    
        public void setLastName(String lastName) {
            this.lastName = lastName;
        }
    
        public boolean isDeleted() {
            return deleted;
        }
    
        public void setDeleted(boolean deleted) {
            this.deleted = deleted;
        }
    
        @Override
        public String toString() {
            return "User [firstName=" + firstName + ", lastName=" + lastName
                    + ", deleted=" + deleted + "]";
        }
    }
    
    public static void main(String[] args) 
    {       
        Group g = new Group();
        g.setId(1);
        g.setName("Test");
    
        User u1 = new User();
        u1.setDeleted(false);
        u1.setFirstName("John");
        u1.setLastName("Jones");
    
        User u2 = new User();
        u2.setDeleted(true);
        u2.setFirstName("Jane");
        u2.setLastName("Jones");
    
        g.addUser(u1);
        g.addUser(u2);
    
        try
        {
            ObjectMapper mapper = new ObjectMapper();
    
            String jsonVal = mapper.writeValueAsString(g);
            System.out.println(jsonVal);
    
            Group grp = mapper.readValue(jsonVal, Group.class);
            System.out.println("Final group: " + grp);
        }
        catch (Exception e)
        {
            System.out.println("Something went wrong...");
            e.printStackTrace();
        }
    }
    
    }
    

    这个的输出:

    {"name":"Test","id":1,"userList":[{"firstName":"John","lastName":"Jones","deleted":false},{"firstName":"Jane","lastName":"Jones","deleted":true}]}
    Final group: Group [name=Test, id=1, userList=[User [firstName=John, lastName=Jones, deleted=false]]]
    

    【讨论】:

    • 听起来很有趣,但据我所知,mapper.readTree 会将漏洞文档(或字符串)缓存为对象,因此如果有成千上万的用户,它已经使用了大量内存?!?我不确定这个...我会在今天晚些时候尝试一下!
    • 添加了我用谷歌搜索的第二种方法,以防它更有益。学习新东西,喜欢它:)
    猜你喜欢
    • 1970-01-01
    • 2015-04-07
    • 1970-01-01
    • 1970-01-01
    • 2017-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-19
    相关资源
    最近更新 更多