如何将这个JSON响应解析为POJO

时间:2018-07-17 00:52:27

标签: java json jackson jackson-databind

我有以下测试班:

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ibm.cio.cloud.cost.model.ElasticResponse;
import com.jayway.jsonpath.JsonPath;

@JsonIgnoreProperties(ignoreUnknown = true)
public class TestJSONPaths {

    private static final String json = "{\"hits\":{\"total\":1,\"hits\":[{\"_id\":\"oEE4j2QBXCNPxFWHqq3i\",\"_score\":1.0,\"_source\":{\"status\":\"SUCCESSFUL\",\"reason\":\"OK, Single ACTIVE status can process\"}}]}}";

    public static void main(String[] args) {
        List<String> strippedJSON = JsonPath.read(json, "$.hits.hits._source");
        ElasticResponse response = null;
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true);

        try {
            System.out.println("From this json string:" + strippedJSON + "\n");
            response = mapper.readValue(strippedJSON.toString(), ElasticResponse.class);
            System.out.println("ElasticDocument=" + mapper.writerWithDefaultPrettyPrinter().writeValueAsString(response.getDocuments()));
        } catch (JsonGenerationException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

这是ElasticResponse类的定义:

public class ElasticResponse {
    private List<ElasticDocument> documents;
    public List<ElasticDocument> getDocuments() {
        return documents;
    }
    public void setDocuments(List<ElasticDocument> documents) {
        this.documents = documents;
    }
}

public class ElasticDocument {
    private String _id;

    private String status;
    private String reason;

   ... getters/setters
}

我正在尝试从给定的JSON映射一个ElasticDocument对象,但它在下面引发了以下错误。我试图将JSON过滤为:[{_source document values}]。此错误发生在Main类的第一行。我该如何映射这个Json?

[DEBUG] Evaluating path: $['hits']['hits']['_source']
Exception in thread "main" com.jayway.jsonpath.PathNotFoundException: Expected to find an object with property ['_source'] in path $['hits']['hits'] but found 'net.minidev.json.JSONArray'. This is not a json object according to the JsonProvider: 'com.jayway.jsonpath.spi.json.JsonSmartJsonProvider'.
    at com.jayway.jsonpath.internal.path.PropertyPathToken.evaluate(PropertyPathToken.java:71)
    at com.jayway.jsonpath.internal.path.PathToken.handleObjectProperty(PathToken.java:81)
    at com.jayway.jsonpath.internal.path.PropertyPathToken.evaluate(PropertyPathToken.java:79)
    at com.jayway.jsonpath.internal.path.PathToken.handleObjectProperty(PathToken.java:81)
    at com.jayway.jsonpath.internal.path.PropertyPathToken.evaluate(PropertyPathToken.java:79)
    at com.jayway.jsonpath.internal.path.RootPathToken.evaluate(RootPathToken.java:62)
    at com.jayway.jsonpath.internal.path.CompiledPath.evaluate(CompiledPath.java:53)
    at com.jayway.jsonpath.internal.path.CompiledPath.evaluate(CompiledPath.java:61)
    at com.jayway.jsonpath.JsonPath.read(JsonPath.java:187)
    at com.jayway.jsonpath.internal.JsonContext.read(JsonContext.java:102)
    at com.jayway.jsonpath.internal.JsonContext.read(JsonContext.java:89)
    at com.jayway.jsonpath.JsonPath.read(JsonPath.java:502)
    at com.ibm.cio.cloud.cost.TestJSONPaths.main(TestJSONPaths.java:18)

1 个答案:

答案 0 :(得分:1)

该异常是由于jsonpath返回一个数组而不是一个对象,因此,如果您将jsonpath修复为如下所示:

$.hits.hits[*]._source

然后它将正确评估。但是,这可能仍然无法实现您想要的功能。.JsonPath.read()将为您反序列化JSON。但是您必须注意这一点:

public class Test {

    private static final String json = "{\"hits\":{\"total\":1,\"hits\":[{\"_id\":\"oEE4j2QBXCNPxFWHqq3i\",\"_score\":1.0,\"_source\":{\"status\":\"SUCCESSFUL\",\"reason\":\"OK, Single ACTIVE status can process\"}}]}}";


    public static void main(String[] args) {
        List<ElasticDocument> docs = JsonPath.read(json, "$.hits.hits[*]._source");

        System.out.println("elasticDoc: " + docs.get(0));
    }

    public static class ElasticDocument {
        public String _id;

        public String status;
        public String reason;

        @Override
        public String toString() {
            return "ElasticDocument{" +
                    "_id='" + _id + '\'' +
                    ", status='" + status + '\'' +
                    ", reason='" + reason + '\'' +
                    '}';
        }
    }
}

它看起来很有效,但是docs List现在实际上是List中的Map个。显然可以在Jackson上注册JsonPath,但我无法使其工作

或者,您可以使用Jackson来反序列化JSON,然后应该创建一个与json结构匹配的对象模型,然后可以使用ObjectMapper来进行反序列化

public class Test {

    private static final String json = "{\"hits\":{\"total\":1,\"hits\":[{\"_id\":\"oEE4j2QBXCNPxFWHqq3i\",\"_score\":1.0,\"_source\":{\"status\":\"SUCCESSFUL\",\"reason\":\"OK, Single ACTIVE status can process\"}}]}}";

    public static void main(String[] args) {

        System.out.println("From this json string:" + json + "\n");

        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true);

        try {

            HitsResource hitsResource = mapper.readValue(json, HitsResource.class);

            System.out.println("jackson elasticDoc: " + hitsResource.hitsParent.hits.get(0).source);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static class HitsResource {
        @JsonProperty("hits")
        public HitsParent hitsParent;

        @Override
        public String toString() {
            return "HitsResource{" +
                    "hitsParent=" + hitsParent +
                    '}';
        }
    }

    public static class HitsParent {
        @JsonProperty("total")
        public Long total;
        @JsonProperty("hits")
        public List<Hits> hits;

        @Override
        public String toString() {
            return "HitsParent{" +
                    "total=" + total +
                    ", hits=" + hits +
                    '}';
        }
    }

    public static class Hits {
        @JsonProperty("_id")
        public String id;
        @JsonProperty("_score")
        public BigDecimal score;
        @JsonProperty("_source")
        public ElasticDocument source;

        @Override
        public String toString() {
            return "Hits{" +
                    "id='" + id + '\'' +
                    ", score=" + score +
                    ", source=" + source +
                    '}';
        }
    }

        public static class ElasticDocument {
            @JsonProperty("_id")
            public String _id;

            @JsonProperty("status")
            public String status;

            @JsonProperty("reason")
            public String reason;

            @Override
            public String toString() {
                return "ElasticDocument{" +
                        "_id='" + _id + '\'' +
                        ", status='" + status + '\'' +
                        ", reason='" + reason + '\'' +
                        '}';
            }
        }
}