使用杰克逊反序列化一个 属性 ,它可以是对象列表或对象

Using jackson deserialising a property which can be List of object or the object

我的库正在调用一个 API,它可以 return 以下任一 JSON 结构 -

{
  "key_is_same" : {
     "inner" : "val"
  } 
}

-或-

 {
  "key_is_same" : [{
     "inner" : "val1"
    },
    {
     "inner" : "val2"
    }
  ]
}

jakson 中是否有任何注释可以处理此问题并将其反序列化为相应的类型

我建议使用 Object 作为动态的 属性 的数据类型。所以这是我的样本。

import java.util.Arrays;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class MainObject {

    private Object key_is_same;

    public Object getKey_is_same() {
        return key_is_same;
    }

    public void setKey_is_same(Object key) {
        this.key_is_same = key;
    }

    public static class KeyObject {
        private String inner;

        public String getInner() {
            return inner;
        }

        public void setInner(String inner) {
            this.inner = inner;
        }

    }

    public static void main(String...s) throws JsonProcessingException {
        MainObject main = new MainObject();
        KeyObject k = new KeyObject();
        k.setInner("val1");
        main.setKey_is_same(k);

        ObjectMapper om = new ObjectMapper();
        System.out.println(om.writeValueAsString(main));

        main.setKey_is_same(Arrays.asList(k, k));
        System.out.println(om.writeValueAsString(main));

        public static void main(String...s) throws IOException {
        MainObject main = new MainObject();
        KeyObject k = new KeyObject();
        k.setInner("val1");
        main.setKey_is_same(k);

        ObjectMapper om = new ObjectMapper();
        System.out.println(om.writeValueAsString(main));

        main.setKey_is_same(Arrays.asList(k, k));
        System.out.println(om.writeValueAsString(main));

        // Deserialize
        MainObject mainWithObject = om.readValue("{\"key_is_same\":{\"inner\":\"val1\"}}", MainObject.class);
        MainObject mainWithList = om.readValue("{\"key_is_same\":[{\"inner\":\"val1\"},{\"inner\":\"val1\"}]}", MainObject.class);
        if(mainWithList.getKey_is_same() instanceof java.util.List) {
            ((java.util.List) mainWithList.getKey_is_same()).forEach(System.out::println);
        }
    }
    }

}

输出

{"key_is_same":{"inner":"val1"}}
{"key_is_same":[{"inner":"val1"},{"inner":"val1"}]}

您似乎在寻找 ACCEPT_SINGLE_VALUE_AS_ARRAY 反序列化功能。

Feature that determines whether it is acceptable to coerce non-array (in JSON) values to work with Java collection (arrays, java.util.Collection) types. If enabled, collection deserializers will try to handle non-array values as if they had "implicit" surrounding JSON array. This feature is meant to be used for compatibility/interoperability reasons, to work with packages (such as XML-to-JSON converters) that leave out JSON array in cases where there is just a single element in array.

Feature is disabled by default.

它可以在 ObjectMapper:

中启用
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);

或通过 @JsonFormat 注释:

@JsonFormat(with = Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
private List<Foo> oneOrMany;

出于说明目的,请考虑以下 JSON 文档:

{
  "oneOrMany": [
    {
      "value": "one"
    },
    {
      "value": "two"
    }
  ]
}
{
  "oneOrMany": {
    "value": "one"
  }
}

可以反序列化为类:

@Data
public class Foo {
    private List<Bar> oneOrMany;
}
@Data
public class Bar {
    private String value;
}

只需确保在您的 ObjectMapper 中启用该功能,或者您的字段带有 @JsonFormat(with = Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) 注释。


如果您正在寻找序列化的等效功能,请参阅 WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED