问题
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)
回答1:
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 + '\'' +
'}';
}
}
}
来源:https://stackoverflow.com/questions/51371785/how-do-i-parse-this-json-response-into-pojo