Getting a value from a Json Response which has " " around parameters - java

I am trying to parse the response from the server something like this
public class TestClass {
public class TaskResponse {
private String id;
private List<String> links;
public String getId(){
return id;
}
}
public static void main(String args[]){
String response = "{
"task": {
"id": 10,
"links": [
{
"href": "http://localhost:9000/v1/115e4ad38aef463e8f99991baad1f809/os-hosts/svs144/onboard/10"
}
]
}
}";
JsonParser parser = new JsonParser();
JsonObject obj = parser.parse(response).getAsJsonObject();
Gson gson = new Gson();
TaskResponse tskResponse = gson.fromJson(response, TaskResponse.class);
String taskId = tskResponse.getId();
System.out.println("The task Id is "+taskId);
}
}
In what I am originally doing I get the task id as null but in this code also which I have written above to try and understand the problem, Eclipse is giving error in the string response, it does not recognize it is a proper string.
Please see to it that I can't change the response string as it is coming from server. Any help of any kind or any links to sort out the error will be highly appreciated.
Thanx in Advance.

Gson will try to match the JSON-string to your class' structure.
Since your JSON starts with task : { ... } it will try to find a property task on the class TaskResponse. Since there's no such field, it won't set anything on your instance.
So either convert it more generally (e.g. using Map.class as the target) or add the task property to a wrapper class:
class TaskResponse {
private Task task;
}
class Task {
private Long id;
private List<Link> links;
}
class Link {
String href;
}
There's also a third option detailed in this answer.

inside the string " can not directly be use
u need to escape it by replacing it to \"
" ===> \"
String response = "{
\"task\": {
\"id\": 10,
\"links\": [
{
\"href\": \"http://`localhost`:9000/v1/115e4ad38aef463e8f99991baad1f809/os-hosts/svs144/onboard/10\"
}
]
}
}";

Related

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_ARRAY

I am trying to parse the incoming Json (given below) to Java object using Gson. The Json request seems to be a valid one, but I am getting the following exception while parsing it.
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_ARRAY at line 5 column 19 path $.metadata.
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:226) ~[gson-2.8.5.jar:?]
at com.google.gson.Gson.fromJson(Gson.java:927) ~[gson-2.8.5.jar:?]
Incoming Json request :
{
"metadata": {
"salesId": "123",
"promoCode": "2010",
"items": [
{
"0": {
"productCode": "1234",
"total": 169900
},
"1": {
"productCode": "4567",
"total": 19900
}
}
]
}
}
Parsing logic :
protected <T extends GenericModel> Optional<T> convertFromJson(final String json, final Class<T> clazz) {
if (StringUtils.isEmpty(json)) {
return Optional.empty();
}
return Optional.of(new Gson().fromJson(json, clazz));
}
Java class :
public class Metadata {
private String salesId;
private String promoCode;
private ArrayList<Object> items = new ArrayList<Object>();
public String getSalesId() {
return salesId;
}
public void setSalesId(String salesId) {
this.salesId = salesId;
}
public String getPromoCode() {
return promoCode;
}
public void setPromoCode(String promoCode) {
this.promoCode = promoCode;
}
public ArrayList<Object> getItems() {
return items;
}
public void setItems(ArrayList<Object> items) {
this.items = items;
}
#Override
public String toString() {
return "Metadata{" +
"salesId=" + getSalesId() +
"promoCode=" + getPromoCode() +
"items=" + getItems() +
'}';
}
}
Please note that Metadata.java is an inner class.
Have been trying to resolve the issue, but no luck. Could anyone let me know how to solve it? TIA.
I'd guess the problem is with the items object in the json you are trying to deserialize.
In the Metadata class items is an ArrayList<Object> but that doesn't tell gson how to deserialize it.
Instead you should try creating another POJO for Item and then making the items an ArrayList<Item>. Something like this: Gson and deserializing an array of objects with arrays in it
You could check if items is the problem by commenting out that attribute and sending in just the salesId and promoCode.
I found out the issue and thought I'l post it here incase someone comes across the same issue. I cleaned the project and rebuild again and it worked fine. The issue was not with the code afterall. I read it on a thread regarding gson libraries and tried it. And it worked for me.
As your json has all data in metadata attribute, I created a new POJO having metadata field.
class ParentMetadata {
private Metadata metadata;
// getters and setters
}
And then parsed json to POJO using below code:
ParentMetadata parentMetadata = new Gson().fromJson(jsonStr, ParentMetadata.class);
This works fine for me.
Also, as items is of type ArrayList<Object>, during debugging I could see items are deserialized as List of LinkedTreeMap.

How to convert JSON to Java object if I do not know all json fields before parsing?

My service can receive several different jsons, such as:
{
"event":"conversation_started",
"context":"context information",
"user":{
"id":"01234567890A=",
"name":"John McClane",
"avatar":"http://avatar.example.com",
"country":"UK",
"language":"en",
"api_version":1
},
"subscribed":false
}
or
{
"event":"message",
"message":{
"type":"text",
"text":"a message to the service",
"location":{
"lat":12.34,
"lon":12.34
}
}
}
or several else jsons. The only field that is the same for all jsons is "event". All other fields can be different (depends on "event" value).
So the question is: how to convert those jsons to java objects (without making messy code)? The only way I know is to manually check "event" value (like json.startsWith("{\n\"event\":\"message\"") but I'm sure that there is any simple decision for doing this.
There are three ways I've done this. The first is to do what you're suggesting - parse the JSON, check the type, and create the object. Be very careful with using a String parser as you may or may not have things like new lines. Instead, do something like:
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(eventString);
String eventType = jsonNode.get("event").asText();
if( eventType.equalsIgnoreCase("conversation_started")) {
// create ConversationStarted object using something like:
ConversationStarted conversationStarted = objectMapper.readValue( eventString, ConversationStarted.class );
}
This, of course, requires all classes to have a concrete POJO to allow for deserialization.
Another way is to do what many other programming languages do and have a key/value map. There are a few ways to do this. One is with the Jackson libraries:
Map<String, Object> map = objectMapper.readValue(eventString, new TypeReference<Map<String,Object>>(){});
Map<String, Object> user = (Map<String, Object>) map.get("user");
System.out.println( "conversation started - avatar is " + user.get("avatar"));
That way you can pass around the Map and extract as needed. Note that you still need to understand the structure of the JSON but you don't need to have a POJO for it.
Lastly is a variation on the second solution. Using JSONPath you can pull out what you need directly. Again you will want to first check out which type of event you have. Something like:
if( JsonPath.read(eventString, "$.event").equals("conversation_started") ) {
String avatar = JsonPath.read(eventString, "$.user.avatar");
System.out.println("conversation started - avatar is " + avatar);
}
The last two methods require you to pull out values one at a time as shown. The first solution gives you a full object to work with. It is your call as to what works best in your environment.
UPD: If you don't want to convert JSON String to JAVA Object via declaring a POJO, you can parse it to JSONObject(com.alibaba.fastjson.JSONObject)
public class Event {
public static void main(String[] args) {
String jsonA = "{\"event\":\"conversation_started\",\"context\":\"context information\",\"user\":{\"id\":\"01234567890A=\",\"name\":\"John McClane\",\"avatar\":\"http://avatar.example.com\",\"country\":\"UK\",\"language\":\"en\",\"api_version\":1},\"subscribed\":false}";
String jsonB = "{\"event\":\"message\",\"message\":{\"type\":\"text\",\"text\":\"a message to the service\",\"location\":{\"lat\":12.34,\"lon\":12.34}}}";
JSONObject jsonObject = JSONObject.parseObject(jsonA);
String event = jsonObject.getString("event");
if (event.equals("message")) {
//do what you want to do
System.out.println("message event......");
} else if ("conversation_started".equals(event)) {
System.out.println("context information event......");
}
}
}
Declaring a class of Event as below, and then convert JSON String to a Event JAVA object.
#Data
public class Event {
private String event;
private String context;
private User user;
private boolean subscribed;
private Message message;
#Data
public static class User {
private String id;
private String name;
private String avatar;
private String country;
private String language;
private int api_version;
}
#Data
public static class Message {
private String type;
private String text;
private Location location;
#Data
public static class Location {
private double lat;
private double lon;
}
}
public static void main(String[] args) {
String jsonA = "{\"event\":\"conversation_started\",\"context\":\"context information\",\"user\":{\"id\":\"01234567890A=\",\"name\":\"John McClane\",\"avatar\":\"http://avatar.example.com\",\"country\":\"UK\",\"language\":\"en\",\"api_version\":1},\"subscribed\":false}";
String jsonB = "{\"event\":\"message\",\"message\":{\"type\":\"text\",\"text\":\"a message to the service\",\"location\":{\"lat\":12.34,\"lon\":12.34}}}";
ObjectMapper objectMapper = new ObjectMapper();
try {
Event eventA = objectMapper.readValue(jsonA, new TypeReference<Event>() {
});
System.out.println(objectMapper.writeValueAsString(eventA));
Event eventB = objectMapper.readValue(jsonB, new TypeReference<Event>() {
});
System.out.println(objectMapper.writeValueAsString(eventB));
} catch (IOException e) {
e.printStackTrace();
}
}
}
Use a JSON object. This is dynamic and can load any json. Then you can reference the event field consistently
Example 1
//import java.util.ArrayList;
//import org.bson.Document;
Document root = Document.parse("{ \"event\" : \"conversation_started\", \"context\" : \"context information\", \"user\" : { \"id\" : \"01234567890A=\", \"name\" : \"John McClane\", \"avatar\" : \"http://avatar.example.com\", \"country\" : \"UK\", \"language\" : \"en\", \"api_version\" : 1 }, \"subscribed\" : false }");
System.out.println(((String)root.get("event")));
Example 2
//import java.util.ArrayList;
//import org.bson.Document;
Document root = Document.parse("{ \"event\" : \"message\", \"message\" : { \"type\" : \"text\", \"text\" : \"a message to the service\", \"location\" : { \"lat\" : 12.34, \"lon\" : 12.34 } } }");
System.out.println(((String)root.get("event")));

Can not get Java object from JSON string(with inner arrays)

I'm trying to get Java Object from JSON string that has inner arrays, there are pretty same questions, but none couldn't solve my problem. Now in console i get MethodPackage.JsonDeserialize#6580cfdd (I'm doing with objectmapper)
My aim is to get separately values in json to do some manupulations
below is my full code:
JSONstring:
{
"status": 1,
"message": "ok",
"sheduleCod": "NOST_A_Persons_m_noaccum",
"algorithms": [{
"cod": "No_st_alg_1",
"kcp": "U6000427",
"dtBeg": "2017-11-01 00:00:00",
"dtEnd": "2017-12-01 00:00:00"
}, {
"cod": "No_st_alg_2",
"kcp": "U6000427",
"dtBeg": "2017-11-01 00:00:00",
"dtEnd": "2017-12-01 00:00:00"
}, {
"cod": "No_st_alg_3",
"kcp": "U6000427",
"dtBeg": "2017-11-01 00:00:00",
"dtEnd": "2017-12-01 00:00:00"
}]
}
Main.class
String jsonString = response.toString();
JsonDeserialize deserialize = objectMapper.readValue(jsonString, JsonDeserialize.class);
System.out.println(deserialize);}
JsonDeserialize.class
public class JsonDeserialize {
private String status;
private String message;
private String sheduleCod;
private List<Algorithm> algorithms;
in JsonDeserialize.class
public class JsonDeserialize {
private String status;
private String message;
private String sheduleCod;
private List<Algorithm> algorithms;
public JsonDeserialize(String status, String message, String sheduleCod, List<Algorithm> algorithms) {
this.status = status;
this.message = message;
this.sheduleCod = sheduleCod;
this.algorithms = algorithms;
}
..... and then getters and setters
Algorithm.class
public class Algorithm {
private String cod;
private String kcp;
private String dtBeg;
private String dtEnd;
public Algorithm(String cod, String kcp, String dtBeg, String dtEnd) {
this.cod = cod;
this.kcp = kcp;
this.dtBeg = dtBeg;
this.dtEnd = dtEnd;
}
public Algorithm () {
}
The output MethodPackage.JsonDeserialize#6580cfdd means that you print the reference and not the values of the object.
To fix this problem override the toString method within the JsonDeserialize class like the following:
#Override
public String toString() {
String values = ""; // you could also use a StringBuilder here
values += "Status: " + status + "\n";
values += "Message: " + message + "\n";
// ....
return values;
}
or use:
System.out.println(deserialize.getStatus())
System.out.println(deserialize.getMessage());
// ...
If you are using Jackson or GSON, you you can just create POJOs that match the structure of the data and it will work automatically. Also, in those pojos you can either make the names of the properties be exactly the same as the JSON has or else use the jackson annotation to let you provide the JSON property name for each object property. But mainly i don't see any getters and setters for your POJOS that you did show, and most likely you do need those. Be carefeul that you name the properties using the right 'bean naming' conventions.

Jackson JSON Convert JSON Object into HashMap

I'm starting using jackson json after Jaunt, but i can't understand some details in deserialization.
I have JSON response from server, here it is:
{
success: true,
stickers: [
{
id: "88899",
name: "",
img: ""
},
{
id: "13161",
name: "3DMAX",
img: ""
}
]
}
I have a Sticker class in my project
public class Sticker {
#JsonProperty("id")
private String id;
#JsonProperty("name")
private String name;
#JsonProperty("img")
private String imgUrl;
//getters and setters and constructors
}
I want to read this response and create a List of Stickers:
List(Sticker) stickerList;
**Another task (if it is possible with jackson tools), i want to create HashMap(String, Sticker) during deserilization instead of List(Sticker) **
How to do it easy and properly?
I have found a solution for List: I created class
public class StickerPage {
#JsonProperty("stickers")
private List<Sticker> stickerList;
public List<Sticker> getStickerList() {
return stickerList;
}
public void setStickerList(List<Sticker> stickerList) {
this.stickerList = stickerList;
}
}
And used it for this:
ObjectMapper objectMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
StickerPage stickerPage = objectMapper.readValue(inputStream, StickerPage.class);
HashMap<String, Sticker> stickerHashMap = new HashMap<>();
for (Sticker sticker : stickerPage.getStickerList()) {
stickerHashMap.put(sticker.getName(), sticker);
}
But it looks weird i think, can you help me with this task?

How to convert Json String with dynamic fields to Object?

I have the followed snipets of Json String:
{
"networks": {
"tech11": {
"id": "1",
"name": "IDEN"
},
"tech12": {
"id": "2",
"name": "EVDO_B"
}
}
}
I use some methods to convert this String to Object:
private static Gson mGson = new Gson();
...
public static WebObjectResponse convertJsonToObject(String jsonString) {
WebObjectResponse webObjectResponse = null;
if(jsonString != null && jsonString.length() > 1){
webObjectResponse = mGson.fromJson(jsonString, WebObjectResponse.class);
}
return webObjectResponse;
}
Where WebObjectResponse is class that should represent above mentioned String.
Its not complicated if I get static fields.
But in my case the values have different names: tech11, tech12 ....
I can use #SerializedName but its works in specific cases like convert "class" to "class_".
As you see networks Object defined as list of tech Objects but with different post-fix.
public class WebObjectResponse{
private DataInfoList networks = null;
}
This is static implementation, i defined 2 values tech11 and tech12 but next response might be techXX
public class DataInfoList {
private DataInfo tech11 = null;
private DataInfo tech12 = null;
}
public class DataInfo {
private String id = null;
private String name = null;
}
What is the good way to convert current Json String to Object where list of elements are Objects too and have different names?
Thank you.
Use a Map!
I would do the following
public class WebObjectResponse {
private Map<String, DataInfo> networks;
}
public class DataInfo {
private String id = null;
private String name = null;
}
// later
Gson gson = new Gson();
String json = "{\"networks\": {\"tech11\": { \"id\": \"1\",\"name\": \"IDEN\" }, \"tech12\": { \"id\": \"2\", \"name\": \"EVDO_B\" } }}";
WebObjectResponse response = gson.fromJson(json, WebObjectResponse .class);
For each object in json networks, a new entry will be added to the Map field of your class WebObjectResponse. You then reference them by techXX or iterate through the keyset.
Assuming a structure like this
{
"networks": {
"tech11": {
"id": "1",
"name": "IDEN"
},
"tech12": {
"id": "2",
"name": "EVDO_B"
},
"tech13": {
"id": "3",
"name": "WOHOO"
}, ...
}
}
We would need your class structure for more details.
As far as I am aware, I think you will need to have some mappings defined somewhere (I used xml's) and then try to match json with one of the mappings to create objects.
Google gson is good. I did it in Jackson
Also, converting objects should be trivial. But since you might have variable fields like tech11 and tech12 , you might want to store the "network" value as a string and then extract fields out of it when required.
Hope I could help.
Edit : Sotirious nails it.
Please use this link for converting SON Response to Java POJO class
http://www.jsonschema2pojo.org/

Categories

Resources