杰克逊杰森将一个对象反序列化为一个列表

Nat*_*ati 5 java serialization json jackson resttemplate

我正在使用Spring RestTemplate和使用反序列化来使用Web服务Jackson.

在我来自服务器的JSON响应中,其中一个字段可以是对象或列表.意思是它可以是"result": [{}]"result": {}.

有没有办法通过对我反序列化的类型的注释来处理这类事情?在第二个例子的情况下,将成员定义为array[]List<>插入单个对象?我可以写一个新的HttpMessageConverter处理它吗?

Kuv*_*dis 6

既然你正在使用杰克逊,我认为你需要的是JsonDeserializer课堂(javadoc).

您可以像这样实现它:

public class ListOrObjectGenericJsonDeserializer<T> extends JsonDeserializer<List<T>> {

    private final Class<T> cls;

    public ListOrObjectGenericJsonDeserializer() {
        final ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
        this.cls = (Class<T>) type.getActualTypeArguments()[0];
    }

    @Override
    public List<T> deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException, JsonProcessingException {
        final ObjectCodec objectCodec = p.getCodec();
        final JsonNode listOrObjectNode = objectCodec.readTree(p);
        final List<T> result = new ArrayList<T>();
        if (listOrObjectNode.isArray()) {
            for (JsonNode node : listOrObjectNode) {
                result.add(objectCodec.treeToValue(node, cls));
            }
        } else {
            result.add(objectCodec.treeToValue(listOrObjectNode, cls));
        }
        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

...

public class ListOrObjectResultItemJsonDeserializer extends ListOrObjectGenericJsonDeserializer<ResultItem> {}
Run Code Online (Sandbox Code Playgroud)

接下来,您需要注释您的POJO字段.比方说,你有类,比如ResultResultItem:

public class Result {

    // here you add your custom deserializer so jackson will be able to use it
    @JsonDeserialize(using = ListOrObjectResultItemJsonDeserializer.class)
    private List<ResultItem> result;

    public void setResult(final List<ResultItem> result) {
    this.result = result;
    }

    public List<ResultItem> getResult() {
        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

...

public class ResultItem {

    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(final String value) {
        this.value = value;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在您可以检查您的反序列化器:

// list of values
final String json1 = "{\"result\": [{\"value\": \"test\"}]}";
final Result result1 = new ObjectMapper().readValue(json1, Result.class);
// one value
final String json2 = "{\"result\": {\"value\": \"test\"}}";
final Result result2 = new ObjectMapper().readValue(json2, Result.class); 
Run Code Online (Sandbox Code Playgroud)

result1result2包含相同的值.


Fed*_*ner 5

您可以使用 Jackson's 中的配置标志实现您想要的ObjectMapper

ObjectMapper mapper = Jackson2ObjectMapperBuilder.json()
    .featuresToEnable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
    .build();
Run Code Online (Sandbox Code Playgroud)

只需按照本答案中的说明将此ObjectMapper实例设置为您的实例,并且在您反序列化的类中,始终使用集合,即 a :RestTemplateList

public class Response {

    private List<Result> result;

    // getter and setter
}
Run Code Online (Sandbox Code Playgroud)