I have a simple Java object that has a String property that contains serialized java objects:
#Data
private class Test {
int id;
String data;
}
The data is created with
test.setData(mapper.writeValueAsString(anyJavaObjectThatShouldBeSerialized));
Then I send the Test Object to another server, where I want to deserialize the object from the data property into a JSONNode:
JsonNode node = mapper.readTree(test.getData());
The problem is, that the result of readTree is a TextNode and not a JsonNode. Therefore I can not access the properties of the serialized data.
The problem might be that the serialized object is interpreted as a String because when I print it it has quotationsmarks around it:
"{\"id\":39,\"name\":\"Im a test value\"}"
How do I get a JsonNode from the String that contains serialized objects? Please note that the data can be ANY Java object, that's why I serialized it into a String.
Make a double deserialization - first deserialize the string payload to json, then deserialize the json to class, or JsonNode in your case.
public class Temp {
public static void main(String[] args) throws Exception {
String payload = //your string payload;
ObjectMapper mapper = new ObjectMapper();
String json = mapper.readValue(payload, String.class);
JsonNode node = mapper.readTree(json);
}
}
As you noted, the cause is that you are making double serialization - first when setting the data field, then again when sending data to the other server.
You can avoid this double serialization/deserialization by making data an object.
#Data
class Test {
int id;
Object data;
}
test.setData(anyJavaObjectThatShouldBeSerialized);
Like this it will be serialized like JsonObject.
{
"id": 39,
"name": "Im a test value"
}
Related
I have a JSON structure that looks like this:
{"data": [{"mykey": "someval"}, {"mykey": "someotherval"}], "foo": "bar"}
I also have
public MyClass {
public String mykey;
}
Now I would like to deserialize the content of "data" of my JSON into a List<MyClass> using Jackson, so I have this code:
ObjectMapper mapper = new ObjectMapper();
List<MyClass> l = (List<MyClass>) mapper.readerFor(new TypeReference<List<MyClass>>(){}).
withRootName("data").readValue(myJSONString);
However this gives me an exception:
com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (FIELD_NAME),
expected END_OBJECT: Current token not END_OBJECT (to match wrapper object with root name
'data'), but FIELD_NAME
Anyone know what I need to do to get this parsed?
Update
List<MyClass> l = (List<MyClass>) mapper.readValue(mapper.readTree(myJSONString).findPath("data").toString(),
new TypeReference<List<MyClass>>(){});
This one line will retrieve the list you are looking for. The problem with what you are trying to do is you are trying to deserialize for the case where the data constitutes the JSON like
{"data":[{"mykey": "someval"}, {"mykey": "someotherval"}]}
But your JSON has additional values which is causing the issue. The above code isolates the data array using the Jackson JSON tree parser and then deserailize it in to the list.
Initial answer
Have a root object so that you can capture the list within that object.
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"data"
})
public class Root {
#JsonProperty("data")
private List<MyClass> data = null;
#JsonProperty("data")
public List<MyClass> getData() {
return data;
}
#JsonProperty("data")
public void setData(List<MyClass> data) {
this.data = data;
}
}
Now use the objectMapper to deserialize to this object.
Root root = mapper.readValue(myJSONString,Root.class);
Let me know how it works out.
My JSON data:
[
"Gi 1/1",
{
"Shutdown":true,
"Speed":"force10ModeFdx",
"AdvertiseDisabled":0,
"MediaType":"dual",
"FC":"off",
"MTU":9600,
"ExcessiveRestart":false,
"PFC":0
}
]
Controlller class method:
public #ResponseBody void setSwitchPortInterfaceInfo(#RequestBody JsonNode jsonNode)
throws JsonProcessingException, IOException { }
When calling this method only "Gi 1/1" got parsed.
Which class do I need to pass as argument to parse complete JSON object?
The JSON Data represent in the question is not present in correct format. We need to convert it into proper version than only parse the Same.
Ideal way of declaring JSON structure is:
[{"key":"value"},{"key":"value"},{"key":"value"}]
ObjectMapper objectMapper = new ObjectMapper();
String strToParse = getString(); // put the string you want to parse
JsonNode node = objectMapper.readValue(strToParse, JsonNode.class);
System.out.println(node.get(0));
System.out.println(node.get(1));
i have a json which contains 2 json Objects
{"cityList":[{"id":"2","cityName":"value"}]}
{"subGuildList":[{"id":"340","guildId":"144","subGuildName":"value"}]}
now i want to combine 2 jsons object to one.
What is the integration of the two json object above?
and how can i to separate main json object with java or android?
use Gson or some similar json converter. your Json in incorrect. if you say 1 json contains those 2 object then it's rep should be:
{
"cityList":[{"id":"2","cityName":"value"}],
"subGuildList":[{"id":"340","guildId":"144","subGuildName":"value"}]
}
Your POJO will be:
public class MyObject {
private List<MyCity> cityList;
private List<MyGuid> subGuidList;
}
public class MyCity {
int id;
String cityName;
}
Is there was a way to pass a String into some Jackson object and have it populate the JSON obj for me? Maybe I'm comparing apples to oranges but the json-rpc-1.0.jar library allows me to do this:
// string will be read in from file but putting the string below just to show what i'm trying to do.
JSONObject jsonObj;
String testStr = "{"blah":123, "aaa": "got here", "foo":"bar", "bar":123}";
jsonObj = new JSONObject(testStr);
jsonObj.put("blah",345);
If I execute
System.out.println(jsonObj);
I get:
{"blah":345, "aaa": "got here", "foo":"bar", "bar":123}
The problem with the json-rpc-1.0.jar file is it doesn't play nicely with long primitive types. For some reason, it converts long data to something like 1.32e9 if I tried to assign a timestamp (long data type) to a field.
I found Jackson (jackson-core-2.2.3.jar) is nicer to longs, preserving the 10-13 digits I need for my timestamp. However, I can't find anything that works like the above snippet of code in Jackson. The closest might be ObjectMapper.readValue but it's not exactly like above.
Please let me know if this is possible or if I'm just dreaming. Thanks in advance for your help. In the meantime, I will try to look at the API some more.
IMO this is not how Jackson is meant to be used. With Jackson, an object should be serialized with the fields of its class. You shouldn't be adding anything to that JSON afterwards. For the sake of the question, however, here's what you can do. Take for example
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
MyClass a = new MyClass();
ObjectNode node = mapper.<ObjectNode>valueToTree(a);
node.put("blah", "123");
System.out.println(node);
}
static class MyClass {
private String value = "some text";
private long timestamp = System.currentTimeMillis();
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
}
which prints
{"value":"some text","timestamp":1384233053765,"blah":"123"}
The valueToTree() method will convert your object into an ObjectNode which is kind of a tree that holds the various JSON elements. You can modify this ObjectNode by adding or removing elements. That is what we do with node.put("blah", "123");. It will add a Json object with name blah and value "123".
Using GSON, how can i return a single key from a Multidimensional Json String?
Here is the Multidimensional Json String:
{"statusCode":0,"statusDescription":"OK","data":{"user":{"id":xxx,"company_id":xxx,"account_type":"5","enable_locations":true,"intuit_user_id":null,"nick_name":"xxx","is_owner":"1","enabled":"1"},"session_token":"xxx"}}
I want to return the "session_token" key value.
I'm trying this:
class app {
static class Response {
String session_token;
}
public void getSessionToken() {
String x = {"statusCode":0,"statusDescription":"OK","data":{"user":{"id":xxx,"company_id":xxx,"account_type":"5","enable_locations":true,"intuit_user_id":null,"nick_name":"xxx","is_owner":"1","enabled":"1"},"session_token":"xxx"}}
Response r = new Gson().fromJson(x, Response.class);
System.out.println(r.session_token);
}
}
But with this, my r.session_token returns null.
You would need to use Gson's JsonParser class directly and extract the data from the parse tree:
String myJsonString = "{\"name\":\"john\",\"lastname\":\"smith\"}";
JsonParser parser = new JsonParser();
JsonElement element = parser.parse(myJsonString);
JsonObject jsonObject = element.getAsJsonObject();
String lastName = jsonObject.get("lastname").getAsString();
System.out.println(lastName);
That said, it's debatable whether this would save you any real time over:
(edited from comments below):
class App {
static class Response {
String lastname;
}
public static void main(String[] args) {
String myJsonString = "{\"name\":\"john\",\"lastname\":\"smith\"}";
Response r = new Gson().fromJson(myJsonString, Response.class);
System.out.println(r.lastname);
}
}
Gson will silently ignore the fact that there's more data in the JSON than you're interested in, and later on you might be interested in it, in which case it's trivial to add fields to your Response class.
Edit due to question changing:
You have a JSON object. It contains a field data whose value is an object. Inside that object you have a field session_token that you're interested in.
Either you have to navigate to that field through the parse tree, or you have to create Java classes that all will map to. The Java classes would resemble (at the bare minimum):
class Response {
Data data;
}
class Data {
String session_token;
}