I'm working on a RESTful app in which the response is passed as JSON string from Extjs to the java , so I am using the jackson to deserialize into the java POJO.
Below is my request:
{
"filter": "[{"type":"string","value":"sdadsadsa","field":"groupName"}]",
"limit": 10
}
The FilterParams class looks like this:
class FilterParams {
#JsonProperty( value = "type" )
private String type;
/** The value. */
#JsonProperty( value = "value" )
private String value;
/** The group name. */
#JsonProperty( value = "field" )
private String field;
}
For conversion to pojo am using below code
mapper.readValue(json, FilterParams.Class);
But still am getting the "Can not deserialize instance of FilterParams" . How to convert it into the pojo.
Any help would be greatly appreciated. Thanks.
Your JSON is invalid. Value of filter shouldn't start with " if it's a JSON array, or should have escaped inner " if it's a String.
Your FilterParams class does not reflect the data in your JSON at all: it should have a limit int property and an array or a Collection of Filters
Then you should have a Filter class with type, value and field properties
Your JSON contains 2 elements : filter & limits so that Jackson is not able to match this JSON String into a FilterParams object.
To ignore the JSON part that deal with limit, do the following :
JsonNode tree = mapper.readTree(<JSON_STRING>);
FilterParams fp = mapper.treeToValue(tree.get("filter"), FilterParams.class);
Related
So I have this variable specCifDetailsReturn which contains the ff. payload
[
{"ax21:cHType":"S",
"ax21:cardNumber":4***********7126,"ax21:returnCde":"00",
"ax21:cancelCode":"",
"ax21:vipCode":"",
"ax21:custrNbr":"0*****3426"},
{"ax21:cHType":"S",
"ax21:cardNumber":4***********3038,"ax21:returnCde":"00",
"ax21:cancelCode":"H",
"ax21:vipCode":"",
"ax21:custrNbr":"0*****3426"}
]
And the ff. Model Class to extract the params I need from the Array
#Data
#AllArgsConstructor
#NoArgsConstructor
#JsonNaming(PropertyNamingStrategy.UpperCamelCaseStrategy.class)
public final class SpecCifInfo {
#JsonAlias("ax21:cHType")
private String cHType;
#JsonAlias("ax21:cardNumber")
private String cardNumber;
}
I am trying to convert it to a Java ArrayList so that I could loop into it and find a card number. But for some reason it always throws a null value on the log even though the specCifDetailsReturn variable has a value. Below is the snippet of my code.
Gson gson = new Gson();
Type type = new TypeToken<List<SpecCifInfo>>(){}.getType();
ArrayList<SpecCifInfo> specDetails = gson.fromJson(specCifDetailsReturn.toString(),type);
for (SpecCifInfo specInfo : specDetails){
LOGGER.debug("Spec CIF Details", specInfo.getCHType() + "-" + specInfo.getCardNumber());
}
Sample Output of the SpecCifInfo Object that has null values
Those annotations are for the Jackson library, and you are manually using Gson. You should either keep them and just let Spring handle the deserialization for you by specifying a List<SpecCifInfo> parameter in the controller method, or you should use GSON's #SerializedName annotation. Either way will work.
i have a json string like this
{
"code": "200",
"data": "",
"datadetail": null,
"message": "Khách hàng không tồn tại",
"description": "KH_NOTFOUND:"
}
because the value of data property is "" so that the object mapper can't not map that field in to Java POJO, is that anyway to modify the value of data property to specific string like below
{
"code": "200",
"data": "no data",
"datadetail": null,
"message": "Khách hàng không tồn tại",
"description": "KH_NOTFOUND:"
}
here is the error
detail
Can not instantiate value of type [collection type; class java.util.ArrayList, contains [simple type, class vnptpay.collection.adapter.partner.water.laichau.Datum]] from String value (''); no single-String constructor/factory method
here is my target java object class to map
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"code",
"data",
"datadetail",
"message",
"description"
})
#JsonIgnoreProperties(ignoreUnknown = true)
public class GetBillResponse implements Serializable{
#JsonProperty("code")
private String code;
#JsonProperty("data")
private ArrayList<Datum> data = null;
#JsonProperty("datadetail")
private Object datadetail;
#JsonProperty("message")
private String message;
#JsonProperty("description")
private String description;
#JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
here is my mapping code
ObjectMapper mapper = new ObjectMapper();
GetBillResponse obj = null;
obj = mapper.readValue(output.toString(), GetBillResponse.class);
Assuming output.toString() is your JSON string you could add .replace("\"\"", \"{none}\"). Java should be able to interpret this as an ArrayList with one element (maybe my syntax is wrong, but there is definitely a way to initialise an ArraList from a String).
Edit: Now that I think about it, you probably need JSON-syntax, not Java-syntax, so .replace("\"\"", \"[]\") or something like that.
As said in the comments, you're mapping from a wrong type.
In your JSON "data": "" refers to a String field name data. When the java code is mapping it, as the default value passed is a string, it tries to look for an ArrayList constructors that takes a String as you defined it as list in your Java code:
#JsonProperty("data")
private ArrayList<Datum> data = null;
So you have 2 options now:
you send a valid JSON array that will be mapped to the list like "data": []. (assuming you have a constructor like Datum(String value))
You change the data mapping in your java code to a String and map it to an ArrayList later (if for instances your splitting the String on commas or so)
Also for the record I wouldn't advise you yo map data to an ArrayList but rather map it to a List as it is common best practice to refer to interfaces and not implementations !
I'm working on a Spring-boot project where I receive different format of Json String. My goal is to convert these Json string into an Unified Java class.
I can receive many variations of this Json:
{ "id" : "someId", "type" : "temperature", "value" : 21.0 }
For example, one variation might look like :
{ "id" : "someId", "data" : { "type": "temp", "val" : 21.0 }, "location": "here" }
So these 2 Json must be mapped into the same Java class.
I already have 2 solutions in mind :
First solution
1) Create a Specific Java Class for each Json that I may receive
2) Create a function that takes this specific object and return the Unified Java Class
Second solution
1) Create a JsonNode with the Json String
2) For each key try to match it with a field of the Unified Java Class.
But we have to take into consideration every key possible of a node like "value" or "val".
What is the best approach to solve this problem ?
I'm looking for a solution that could be easy to maintain.
Edit : I'm already using Jackson, but my problem is to map this Json object into an universal Java Class independently of the Json
Edit 2 : The Unified Java Class is a class model that already exist and it's used to store information in our database. So to push information inside our database, I have to convert each json I receive into this unified format
I can see following solutions. E.g. you use Jackson for parse JSON you could declare you custom ObjectMapper:
ObjectMapper mapper = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
This mapper contains additional options to ignore unknow properties.
Do you Map<String, Object> as destination class. This is magic key and it works always. Contra: you do not have json validation and have to add many constant keys to read this.
Example:
public static <T> Map<String, T> readMap(String json) throws NGPException {
if (json == null) {
return null;
}
ObjectReader reader = JSON_MAPPER.readerFor(Map.class);
MappingIterator<Map<String, T>> it = reader.readValues(json);
if (it.hasNextValue()) {
Map<String, T> res = it.next();
return res.isEmpty() ? Collections.emptyMap() : res;
}
return Collections.emptyMap();
}
Client:
Map<String, Object> map = readMap("json string");
String id = (String)map.getOrDefault("id", null);
Second way is to build one general class that contain all posiible variables. Additionnaly you have to set option to Jackson ignore unknown fields. In this case, existed fields will be used by Jackson.
Example:
public static <T> T read(String json, Class<T> clazz) throws NGPException {
return mapper.readerFor(clazz).readValue(json);
}
class Response {
private String id;
private String type;
private Double value;
private String location;
private Data data;
public class Data {
private String type;
private String temp;
private Double value;
}
}
Client:
Response response = read("json string", Response.class);
I usually use GSon from Google. It is really usefull. Check gson.fromJson(yourJsonString) in your case.
You can easy use
Gson gson = new Gson();
Data data = gson.fromJson(jsonString, Data.class);
Right now I am using Gson to deserialize JSON to Object.
The JSON looks like this:
[
{
"hash":"c8b2ce0aacede58da5d2b82225efb3b7",
"instanceid":"aa49882f-4534-4add-998c-09af078595d1",
"text":"{\"C_FirstName\":\"\",\"ContactID\":\"2776967\",\"C_LastName\":\"\"}",
"queueDate":"2016-06-28T01:03:36"
}
]
And my entity object looks like this:
public class AppCldFrmContact {
public String hash;
public String instanceid;
public HashMap<String,String> text;
public String queueDate;
}
If text was a String data type, everything would be fine. But then I wouldn't be able to access different fields as I want to.
Is there a way to convert given JSON to Object I want?
The error I am getting is: Expected BEGIN_OBJECT but was STRING at line 1 column 174, which is understandable if it cannot parse it.
The code doing the parsing:
Type listType = new TypeToken<List<AppCldFrmContact>>() {
}.getType();
List<AppCldFrmContact> contacts = gson.fromJson(response.body, listType);
For you expected result, JSON data should be like below format,
[
{
"hash":"c8b2ce0aacede58da5d2b82225efb3b7",
"instanceid":"aa49882f-4534-4add-998c-09af078595d1",
"text":{"C_FirstName":"","ContactID":"2776967","C_LastName":""},
"queueDate":"2016-06-28T01:03:36"
}
]
You are getting this error because text field is a JSON map serialized to the string. If it is an actual your data and not a just an example, you can annotate a field with #JsonDeserialize and write your own custom JsonDeserializer<HashMap<String,String>> which will make deserialization 2 times.
Given the following JSON object
{
"id": 5,
"data: { ... }
}
Is it possible to map this to the following POJO?
class MyEntity {
int id;
Map<String, Object> data;
}
Because I would like to leave the data object open ended. Is this even possible or what is a better approach to go about this? I am doing this on Android.
I don't have any idea about Android application but you can achieve it using Gson library easily.
The JSON that is used in your post is not valid. It might be a typo. Please validate it here on JSONLint - The JSON Validator
Simply use Gson#fromJson(String, Class) method to convert a JSON string into the object of passed class type.
Remember the name of instance member must be exactly same (case-sensitive) as defined in JSON string as well. Read more about JSON Field Naming
Use GsonBuilder#setPrettyPrinting() that configures Gson to output Json that fits in a page for pretty printing.
Sample code:
String json = "{\"id\": 5,\"data\": {}}";
MyEntity myEntity = new Gson().fromJson(json, MyEntity.class);
String prettyJsonString = new GsonBuilder().setPrettyPrinting().create().toJson(myEntity);
System.out.println(prettyJsonString);
output:
{
"id": 5,
"data": {}
}