简体   繁体   中英

How do I parse this JSON response into POJO

I have the following Test class:

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();
        }
    }
}

Here is the ElasticResponse class def:

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
}

I'm trying to get a ElasticDocument object mapped from the JSON given but it's throwing the following errors below. I'm attempting to filtered out the JSON to simply be: [{_source document values }]. This error occurs on the very first line in the Main class. How can I map this 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)

The exception is due to the jsonpath returning an array instead of an object, so if you fix the jsonpath to look like this:

$.hits.hits[*]._source

Then it will evaluate properly. However, this probably still doesn't do what you want it to do.. The JsonPath.read() will deserialise the JSON for you. But you have to watch out with this:

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 + '\'' +
                    '}';
        }
    }
}

Looks like it works, however the docs List is now actually a List of Map s. Apparently It's possible to register JsonPath with Jackson but I can't make it work

Alternatively you can use Jackson to deserialise the JSON, then you should create an object model that matches the json structure and then you can use the ObjectMapper to do the deserialisation

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 + '\'' +
                        '}';
            }
        }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM