Jackson Read Value as String
I Have an Object with Unknown Values, Say { "Data": [ {"A": .. ., "Dont_Know_What_Else_Is_Here": .. .. } ] } and I Just Want to Store the Value of "Data" as a...
I have an object with unknown values, say
{
"data": [
{"a":...,
"dont_know_what_else_is_here":....}
]
}
And I just want to store the value of "data" as a string into a variable/database.
How should I read it from the streaming API?
9 Answers
When we try to fetch data in form of string from JsonNode,we usually use asText, but we should use textValue instead.
asText: Method that will return a valid String representation of the container value, if the node is a value node (method isValueNode() returns true), otherwise empty String.
textValue: Method to use for accessing String values. Does NOT do any conversions for non-String value nodes; for non-String values (ones for which isTextual() returns false) null will be returned. For String values, null is never returned (but empty Strings may be)
So Let's take an example,
JsonNode getJsonData(){
ObjectMapper mapper = new ObjectMapper();
ObjectNode node = mapper.createObjectNode();
node.put("anyParameter",null);
return node;
}
JsonNode node = getJsonData();
json.get("anyParameter").asText() // this will give output as "null"
json.get("").textValue() // this will give output as null
You can get the data in a map according to key value pairs.
Map<String, Object> mp = mapper.readValue(new File("xyz.txt"),new TypeReference<Map<String, Object>>() {});
Now get the value from map:
mp.get("data");
Assuming you've got a parser already and it points to "data" token (e.g. from custom deserializer) you can do the following:
ObjectMapper mapper = new ObjectMapper();
JsonNode treeNode = mapper.readTree(parser);
return treeNode.toString();
This will get you String containing the value of the "data".
You can have some Entity class for JSON result.
String json = "your_json";
ObjectMapper mapper = new ObjectMapper();
Entity entity = mapper .readValue(json, Entity.class);
// here you can do everything with entity as you wish
// to write Entity value as String when you wish
String text = mapper.writeValueAsString(object);
// to write Entity child's value as String when you wish (let's data contain data part)
String data = mapper.writeValueAsString(object.getData());
Let's say you have a POJO java class called User(Taken from this)
public class User {
public enum Gender { MALE, FEMALE };
public class Name {
private String _first, _last;
public String getFirst() { return _first; }
public String getLast() { return _last; }
public void setFirst(String s) { _first = s; }
public void setLast(String s) { _last = s; }
}
private Gender _gender;
private Name _name;
private boolean _isVerified;
private byte[] _userImage;
public Name getName() { return _name; }
public boolean isVerified() { return _isVerified; }
public Gender getGender() { return _gender; }
public byte[] getUserImage() { return _userImage; }
public void setName(Name n) { _name = n; }
public void setVerified(boolean b) { _isVerified = b; }
public void setGender(Gender g) { _gender = g; }
public void setUserImage(byte[] b) { _userImage = b; }
}
So now you have JSON string which is coming from any place somewhere like web socket or somewhere else.As an example assume this is the string you are getting
String json = "{\n" +
" \"name\" : { \"first\" : \"Joe\", \"last\" : \"Sixpack\" },\n" +
" \"gender\" : \"MALE\",\n" +
" \"verified\" : false,\n" +
" \"userImage\" : \"Rm9vYmFyIQ==\"\n" +
"}";
Now you can convert this JSON string into POJO object just using this piece of code.
ObjectMapper mapper = new ObjectMapper();
User user = mapper .readValue(json, User.class);
I assume you just want to read a sub-tree from input using Streaming API -- but in the end, you need to whole sub-tree as one thing to store in DB (or variable).
So what you probably want to use is JsonParser.readValueAs(MyType.class) -- this will call ObjectMapper (and for it to work, parser has to be created via JsonFactory accessed from ObjectMapper; or you need to call JsonFactory.setCodec(mapper)).
If content is arbitrary, you can read it as Map or JsonNode:
Map<String,Object> map = parser.readValueAs(Map.class);
// or
JsonNode root = parser.readValueAsTree();
as soon as JsonParser is pointing to START_ELEMENT of the JSON Object you want to databind.
If using String data in createParser(data), i use this method to collect string content with streaming api:
if ("data".equals(fieldname))
String strData = getValueAsString(jp);
and
private static String getValueAsString(JsonParser jp)
throws com.fasterxml.jackson.core.JsonParseException, IOException {
JsonToken token = jp.getCurrentToken();
int counter = 0;
long startIndex = jp.getCurrentLocation().getCharOffset();
long endIndex = 0;
if (token == JsonToken.START_OBJECT) {
// JsonLocation location = jp.getCurrentLocation();
// startIndex = location.getCharOffset();
// System.out.println(",location=" + new Gson().toJson(location) +
// ", start=" + startIndex);
counter++;
while (counter > 0) {
token = jp.nextToken();
if (token == JsonToken.START_OBJECT)
counter++;
if (token == JsonToken.END_OBJECT) {
counter--;
endIndex = jp.getCurrentLocation().getCharOffset();
}
}
return data.substring((int) startIndex - 1, (int) endIndex);
} else if (token == JsonToken.START_ARRAY) {
counter++;
while (counter > 0) {
token = jp.nextToken();
if (token == JsonToken.START_ARRAY)
counter++;
if (token == JsonToken.END_ARRAY) {
counter--;
endIndex = jp.getCurrentLocation().getCharOffset();
}
}
return data.substring((int) startIndex - 1, (int) endIndex);
} else {
return jp.getText();
}
}
it works when data source is String. for none string source such as file, using JsonLocation.getByteOffset() instead of JsonLocation.getCharOffset()
Finally figured out the solution from reading the tutorial page.
Just to give others a pointer here:
Switch to using a MappingJSONFactory when creating the parser:
HttpResponse response = client.execute(request); JsonFactory jfactory = new MappingJsonFactory(); JsonParser parser=jfactory.createJsonParser(response.getEntity().getContent());Then you can just do
parser.readValueAsTree().toString();
or parse it however you want.