【问题标题】:Jackson mapping Object or list of Object depending on json input杰克逊映射对象或对象列表取决于 json 输入
【发布时间】:2014-01-11 14:20:54
【问题描述】:

我有这个 POJO:

public class JsonObj {

    private String id;
    private List<Location> location;


    public String getId() {
        return id;
    }

    public List<Location> getLocation() {
        return location;
    }

    @JsonSetter("location")
    public void setLocation(){
        List<Location> list = new ArrayList<Location>();
        if(location instanceof Location){
            list.add((Location) location);
            location = list;
        }
    }
}

json 输入中的“位置”对象可以是简单的位置实例或位置数组。当它只是一个实例时,我会收到此错误:

Could not read JSON: Can not deserialize instance of java.util.ArrayList out of   START_OBJECT token

我尝试实现自定义设置器,但没有成功。如何根据 json 输入映射位置或列表?

【问题讨论】:

  • 不同的 JSON 意味着不同的 JSON DTO。如果你的 JSON 有一个[],你需要使用List,如果它有一个{},你需要一个简单的对象。
  • 同一个键有时是 [] 有时是 {},不幸的是我无法更改。
  • 创建一个自定义反序列化程序,检查它是[] 还是{},并适当地创建一个实例并将其添加到List
  • 这似乎是解决方案。你能提供一些代码或文档来帮助我实现这个吗?
  • 只需谷歌jackson deserializer。类似this.

标签: java android json jackson rest-client


【解决方案1】:

更新:Mher Sarkissian's soulution 工作正常,它也可以与 here 建议的注释一起使用,如下所示:。

@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
private List<Item> item;

对于这个最烦人的问题,我深表同情,我也遇到了同样的问题,在这里找到了解决方案:https://stackoverflow.com/a/22956168/1020871

稍微修改一下,我想出了这个,首先是泛型类:

public abstract class OptionalArrayDeserializer<T> extends JsonDeserializer<List<T>> {

    private final Class<T> clazz;

    public OptionalArrayDeserializer(Class<T> clazz) {
        this.clazz = clazz;
    }

    @Override
    public List<T> deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException {
        ObjectCodec oc = jp.getCodec();
        JsonNode node = oc.readTree(jp);
        ArrayList<T> list = new ArrayList<>();
        if (node.isArray()) {
            for (JsonNode elementNode : node) {
                list.add(oc.treeToValue(elementNode, clazz));
            }
        } else {
            list.add(oc.treeToValue(node, clazz));
        }
        return list;
    }
}

然后是属性和实际的反序列化器类(Java 泛型并不总是很漂亮):

@JsonDeserialize(using = ItemListDeserializer.class)
private List<Item> item;

public static class ItemListDeserializer extends OptionalArrayDeserializer<Item> {
    protected ItemListDeserializer() {
        super(Item.class);
    }
}

【讨论】:

【解决方案2】:

jackson 已经支持这个了

objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-10
    • 1970-01-01
    • 2013-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多