Reputation: 3511
The JSON string is as follows
{
"rank":"-text_relevance",
"match-expr":"(label 'star wars')",
"hits":{
"found":7,
"start":0,
"hit":[
{"id":"tt1185834",
"data":{
"actor":["Abercrombie, Ian","Baker, Dee","Burton, Corey"],
"title":["Star Wars: The Clone Wars"]
}
},
.
.
.
{"id":"tt0121766",
"data":{
"actor":["Bai, Ling","Bryant, Gene","Castle-Hughes, Keisha"],
"title":["Star Wars: Episode III - Revenge of the Sith"]
}
}
]
},
"info":{
"rid":"b7c167f6c2da6d93531b9a7b314ad030b3a74803b4b7797edb905ba5a6a08",
"time-ms":2,
"cpu-time-ms":0
}
}
It has many fields, but I just have want the Data field. This won't work:
mapper.readvalue(jsonString,Data.class);
How do I make Jackson read just the "Data" field?
Upvotes: 27
Views: 32975
Reputation: 479
Jackson 2.3 now has a JsonPointer class you can use. There's a simple example in their quick overview for the release.
Usage is simple: for JSON like
{ "address" : { "street" : "2940 5th Ave", "zip" : 980021 }, "dimensions" : [ 10.0, 20.0, 15.0 ] }
you could use expressions like:
JsonNode root = mapper.readTree(src); int zip =root.at("/address/zip").asIntValue(); double height = root.add("/dimensions/1").asDoubleValue();// assuming it's the second number in there
Upvotes: 34
Reputation: 59607
I think that the easiest way to do this is using the Jackson TreeModel: let Jackson parse the JSON input into a JsonNode
object that you then query, assuming some knowledge of the data structure. This way you can ignore most of the data, walking down the JsonNodes
to the data that you want.
// String input = The JSON data from your question
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readValue(input.getBytes(), JsonNode.class);
// can also use ArrayNode here, but JsonNode allows us to get(index) line an array:
JsonNode hits = rootNode.get("hits");
// can also use ObjectNodes here:
JsonNode oneHit = null;
JsonNode dataObj = null;
int idx = 0;
Data data = null;
if (hits != null)
{
hits = hits.get("hit");
if (hits != null)
{
while ((oneHit = hits.get(idx)) != null)
{
dataObj = oneHit.get("data");
System.out.println("Data[" + idx + "]: " + dataObj);
idx++;
}
}
}
Output:
Data[0]: {"id":"tt1185834","data":{"actor":["Abercrombie, Ian","Baker, Dee","Burton, Corey"],"title":["Star Wars: The Clone Wars"]}}
Data[1]: {"id":"tt0121766","data":{"actor":["Bai, Ling","Bryant, Gene","Castle-Hughes, Keisha"],"title":["Star Wars: Episode III - Revenge of the Sith"]}}
You can still use your Data
class implementation, but I believe this will require getting the String
representing each data
- as above relying on toString
, or using JsonNode.getText()
- and re-parsing it using the ObjectMapper
:
mapper.readValue(dataArray, Data.class));
The alternative is to use the Jackson Streaming Model, and intercept the nodes yourself until you see the part of the input that marks the beginning of each data
element, then consume the string and call objectMapper.readValue
on the contents, for each string.
Upvotes: 15
Reputation: 49915
Json-path could be a very good alternative for such a requirement - if you are okay with a solution other than Jackson that is: http://code.google.com/p/json-path/
Upvotes: 5