如何反序列化JSON数组?

7
我正在使用CXF中的Jackson来序列化/反序列化数据。不幸的是,我在配置CXF/Jackson以反序列化JSON数组方面遇到了困难。希望能帮助解决这个问题。
到目前为止,大多数JSON数据都是对象格式,即:
{ "objectCollection": [ {...}, {...}, {...}... ] }
然而,问题中的JSON数据是以下形式:
[ {...}, {...}, {...} ]
Web服务端点期望一个"GroupsDto"对象(请参见下文),它有一个单一的属性——一个组合集合,通过JSON数组传输。
@PATH(...)
public Response createGroups(GroupsDto groups) {
...
}

我将@ JsonDeserialize添加到GroupsDto集合属性中,但它不起作用。 我仍然会收到“无法将START_ARRAY令牌反序列化为GroupsDto实例”的消息。
public class GroupsDto {

       private Collection<GroupDto> groups;

       /**
        * @return the groups
        */
       @XmlElement(name="group")
       @JsonDeserialize(contentAs=GroupDto.class)
       public Collection<GroupDto> getGroups() {
               return groups;
       }
...
}

3个回答

9
如果JSON数据的格式为:
[ {...}, {...}, {...} ]

您需要使用添加另一个类名“wrapper”:

您需要使用添加另一个类名“wrapper”:

@JsonIgnoreProperties(ignoreUnknown = true)
public class ListDto extends ArrayList<GroupDto> {

    public ListDto() {
    }
}

在反序列化时使用这个类。这种方法对我很有效。


1

您只需要在您的setter中指定@JsonDeserialize(contentAs=GroupDto.class)。序列化始终在get上进行,反序列化始终在set上进行,或者如果您愿意,您可以在字段上同时指定两者。

SerializeDeserialize的文档

代码示例:

import java.io.IOException;
import java.util.List;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.annotate.JsonDeserialize;

public class JacksonDeserialize {

    public static class ModelClass {

        private String name;

        public ModelClass() {
        }

        public String getName() {
            return name;
        }

        public void setName(final String name) {
            this.name = name;
        }

        public ModelClass(final String name) {
            super();
            this.name = name;
        }

        @Override
        public String toString() {
            return "ModelClass [name=" + name + "]";
        }

    }

    public static class ListModelClass {

        private List<ModelClass> list;

        @JsonDeserialize(contentAs = ModelClass.class)
        public void setList(final List<ModelClass> list) {
            this.list = list;
        }

        @Override
        public String toString() {
            return "ListModelClass [list=" + list + "]";
        }

    }

    public static void main(final String[] args) throws JsonGenerationException, JsonMappingException, IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        System.out.println(objectMapper.readValue("{\"list\":[{\"name\":\"name1\"},{\"name\":\"name2\"}]}",
                ListModelClass.class));
    }

}

感谢您提醒getter/setter问题。我注意到在您的示例中,您正在限定json数组,即"{"list":...}"。是否有可能在不限定的情况下反序列化?如果可以,该如何实现? - Ari
在这种情况下,没有资格要求,魔法是通过@JsonDeserialize注释完成的。属性contentAs用于指示这是一个集合,并将反序列化为ModelClass。如果您愿意,可以将属性名称从“list”更改为其他内容。名称并不重要,重要的是注释。 - Francisco Spaeth
我明白具体名称并不重要,但如果没有名称怎么办?在你的例子中,你正在读取{"list": [...]},它有一个名为'list'的键,但如果没有键(名称)呢?例如[...] - Ari
啊,问题就在这里。序列化/反序列化由CXF处理,它调用预定义的“ObjectMapper”;因此,我不能简单地将“TypeReference”传递给自定义的“ObjectMapper”,我必须依赖于预定义的“ObjectMapper”和注释。 - Ari
好的,你在使用哪个库来集成两者? - Francisco Spaeth
没有集成库;CXF允许指定预定义的处理程序。 - Ari

0

不使用包装类

使用Jackson的ObjectMapper

objectMapper.readValue();

数据如下...

[... , {YourObj} , {YourObj} , ... ]

你可以这样做

YourObj[] yourObjArray = objectMapper.readValue(source, YourObj[].class);


如果您想将其转换为列表,可以进一步执行以下操作

List<YourObj> yourObjList = Arrays.stream(yourObjArray).collect(Collectors.toList())

Reference https://www.baeldung.com/jackson-collection-array


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接