Jackson objectMapper mapping different json properties to same pojo - java

I have a very simple json which I am trying to map to an object.
JSON :
[
{
"cust_lpid": "0119b9f7f99ad2161de7b0b",
"cust_uid": "soumavtestflow"
}
]
My Mapper Class:
#JsonIgnoreProperties(ignoreUnknown = true)
public class CustomerSegmentRequest {
#JsonProperty("LPID")
String cust_lpid;
#JsonProperty("UserId")
String cust_uid;
public String getCust_lpid() {
return cust_lpid;
}
public void setCust_lpid(String cust_lpid) {
this.cust_lpid = cust_lpid;
}
public String getCust_uid() {
return cust_uid;
}
public void setCust_uid(String cust_uid) {
this.cust_uid = cust_uid;
}
}
When I do a
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
LPIDCustIDMapper[] custSegResp = objectMapper.readValue(responseBody,CustomerSegmentRequest [].class);
I don't get any values populated in custSegResp.
However when i remove the #JsonProperty it works.
I need the json property name to map an incoming request and hence don't wanna create a separate mapping class.
Is there a way to achieve the same?

use #JsonAlias
#JsonIgnoreProperties(ignoreUnknown = true)
public class CustomerSegmentRequest {
#JsonAlias({"cust_lpid", "LPID" })
String cust_lpid;
#JsonAlias({"cust_uid", "UserId" })
String cust_uid;
public String getCust_lpid() {
return cust_lpid;
}
public void setCust_lpid(String cust_lpid) {
this.cust_lpid = cust_lpid;
}
public String getCust_uid() {
return cust_uid;
}
public void setCust_uid(String cust_uid) {
this.cust_uid = cust_uid;
}
}

#JsonProperty("keyName") is to specify what is the key is the JSON which maps to this field.
The reason it works without it is, without it Jackson tries to first match via getters/setters after removing the get/set prefix keys and normalizing the case (getAbCd -> abCd), which in your case gives the keys as in the JSON.
You need to modify your #JsonProperty("LPID") to #JsonProperty("cust_lpid") or if you need to map to multiple keys use #JsonAlias({"cust_lpid", "LPID" })

Related

How do I have two identical json property names assigned to two separated fields

I have the following Java class
I need to serialize it to json in the following way:
if the list(paymentTransactionReport field) is not null display it values -
{
"paymentTransactionResponse" : [
{},
{}
]
}
if the list is null I need to display the paymentTransactionReportError in json field with name 'paymentTransactionResponse', as in previous case. Example -
{
"paymentTransactionResponse" : {
----
//fields from PaymentTransactionReportError class
----
}
}
How can I do this?preferably without custom serializers.
If use just two annotations #JsonProperty with the same name and JsonInclude.NON_NULL as I did, I have this error: No converter found for return value of type:... Seems to be that is a error happened during serialization because of fields with the same name
One way you can achieve this is, using #JsonAnyGetter, Try this
public class TestDTO {
#JsonIgnore
List<String> paymentTransactionResponse;
#JsonIgnore
String paymentTransactionResponseError;
public List<String> getPaymentTransactionResponse() {
return paymentTransactionResponse;
}
public void setPaymentTransactionResponse(List<String> paymentTransactionResponse) {
this.paymentTransactionResponse = paymentTransactionResponse;
}
public String getPaymentTransactionResponseError() {
return paymentTransactionResponseError;
}
public void setPaymentTransactionResponseError(String paymentTransactionResponseError) {
this.paymentTransactionResponseError = paymentTransactionResponseError;
}
#JsonAnyGetter
public Map<String, Object> getData(){
Map<String, Object> map = new HashMap<String, Object>();
if(paymentTransactionResponse != null) {
map.put("paymentTransactionResponse", paymentTransactionResponse);
}else {
map.put("paymentTransactionResponse", paymentTransactionResponseError);
}
return map;
}}

How do I create Json Array in Java8 and only print json if I set value for it?

I am trying to generate the following using fasterxml jackson.. but I am stuck. I can't seem to work out how to create arrays.
{
"setAccId":"12345",
"groupOf":null,
"isEnabled":false,
"list":[
{
"student":"jim",
"type":"S_A",
"retro":null
},
{
"student":"bob",
"type":"S_A",
"retro":null
}
],
"sort":[]
}
I have two classes. One has the Json properties, and the other is where I print it.
Below class (DynamicJsonHelper) is where I have all the json properties
package com.company.jsonfc;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
#JsonPropertyOrder({
"accId",
"groupOf",
"isEnabled"
})
public class DynamicJsonHelper {
public String accId;
public String groupOf;
public List studentList;
#JsonProperty("accId")
public void setAccId(String accId) {
this.accId = accId;
}
#JsonProperty("groupOf")
public void setGroupOf(String groupOf) {
this.groupOf = groupOf;
}
#JsonProperty("isEnabled")
public boolean isEnabled() {
return false;
}
#JsonProperty("studentList")
public List<StudentList> studentList() {
return studentList;
}
}
Student List Class (as suggested)
class StudentList {
String student;
String type;
String retro;
}
And here is class (PrintJson) where I call it.
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.company.jsonfc.DynamicJsonHelper;
#JsonInclude(JsonInclude.Include.NON_NULL)
public class PrintJson {
#Test
public void create_json() throws JsonProcessingException {
final JsonNodeFactory factory = JsonNodeFactory.instance;
DynamicJsonHelper dynamicJsonHelper = new DynamicJsonHelper();
String jsonString;
ObjectMapper mapper = new ObjectMapper();
dynamicJsonHelper.setAccId("12345");
jsonString = mapper.writeValueAsString(dynamicJsonHelper);
System.out.println(jsonString);
}
}
This results in printing the following:
{
"setAccId":"12345",
"groupOf":null,
"isEnabled":false
"studentList":null
}
1) How do I add the list:[ ... ] array & the sort: [ ] at the end too?
2) In class PrintJson, I don't set value for groupOf but it is still created in Json. How do I set it so if I set value, it is printed.. otherwise it is not included in the json being printed.
I would appreciate if you took my code and gave me example based on it for better understanding please
1) How do I add the list:[ ... ] array & the sort: [ ] at the end too?
Answer: You can create two more classes one for list and one for sort. Now in the class DynamicJsonHelper you can add both of them like you have added accId or isEnabled
and they will be printed. Make sure to add the fields you want in them as instance variables in both of the classes. For example for list you can have a class like:
class StudentList{
String student;
String type;
String retro;
}
Now add a field in your class DynamicJsonHelper as List<StudentList>. Similarly you can do for sort.
2) In class PrintJson, I don't set value for groupOf but it is still
created in Json. How do I set it so if I set value, it is printed..
otherwise it is not included in the json being printed.
Answer: You can either use Object mapper and set it to ignore the null fields during serialization. For eg: mapper.setSerializationInclusion(Include.NON_NULL);
Or you can set it at class level to ignore null values if any. For eg:
#JsonInclude(Include.NON_NULL)
class Test
{
String t;
}
As mentioned in the comments by aBnormaLz above doesn't work if the type is primitive like you have for isEnabled. So consider changing it to Boolean and ensure the same for other fields also.
Edit:
#JsonPropertyOrder({
"accId",
"groupOf",
"isEnabled"
})
#JsonInclude(JsonInclude.Include.NON_NULL)
public class DynamicJsonHelper {
public String accId;
public String groupOf;
public List<Student> studentList;
#JsonProperty("accId")
public void setAccId(String accId) {
this.accId = accId;
}
#JsonProperty("groupOf")
public void setGroupOf(String groupOf) {
this.groupOf = groupOf;
}
#JsonProperty("isEnabled")
public boolean isEnabled() {
return false;
}
#JsonProperty("studentList")
public void setStudentList(List<Student> list) {
this.studentList = list;
}
}
class Student {
private String student;
private String type;
private String retro;
public Student(String student, String type, String retro) {
this.student = student;
this.type = type;
this.retro = retro;
}
public String getStudent() {
return student;
}
public void setStudent(String student) {
this.student = student;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getRetro() {
return retro;
}
public void setRetro(String retro) {
this.retro = retro;
}
}
class HelperTest{
public static void main(String[] args) throws JsonProcessingException {
DynamicJsonHelper dynamicJsonHelper = new DynamicJsonHelper();
String jsonString;
ObjectMapper mapper = new ObjectMapper();
dynamicJsonHelper.setAccId("12345");
List<Student> list = Arrays.asList(new Student("s1", "t1", "r1"), new Student("s2", "t2", "r2"));
dynamicJsonHelper.setStudentList(list);
jsonString = mapper.writeValueAsString(dynamicJsonHelper);
System.out.println(jsonString);
}
}
After executing the program the output is as shown below:
{
"accId": "12345",
"isEnabled": false,
"studentList": [
{
"student": "s1",
"type": "t1",
"retro": "r1"
},
{
"student": "s2",
"type": "t2",
"retro": "r2"
}
]
}
You missed a point that you have to have third class and it must have property of type java.util.List or array and name list for your example.
e.g.
public class JsonHolder {
// appropriate Json/Jackson annotations ommitted
private String setAccId;
private String groupOf;
private boolean isEnabled;
private List<DynamicJsonHelper> list;
private String[] sort;
// .. getter/setters ...
}
then you have to create that object and when you created your DynamicJsonHelper put it into list or array.
After all you can serialize JsonHolder object and you will see your java List or Array as JSON array.
UPD: just note that in JSON structure like { ... } is an object and in Java there must be a class for it.
So, starting with JSON structure you posted
{
"setAccId":"12345",
"groupOf":null,
"isEnabled":false,
"list":[
{
"student":"jim",
"type":"S_A",
"retro":null
},
{
"student":"bob",
"type":"S_A",
"retro":null
}
],
"sort":[]
}
it is an object (let name it JsonHolder) with properties named setAcctId, groupOf, isEnabled, list, sort
So you have to have a Java class for it (similar as you did for your DynamicJsonHelper. You can use any #Json annotations you'd like to the same way (I omitted them and left for you). Even you will not have them Jackson or any other JSON serialiser will use property names in Java class by as default.
I mean as example your #JsonProperty("accId")
#JsonProperty("accId")
public void setAccId(String accId)
is not required as long as getter/setter/property named also getAcctId, setAcctId, acctId. Jackson will use that if there is no #JsonProperty annotation.
BTW it is better to do it as you did for code readability. :-)
Per your question:
list and sort properties in JSON are arrays. Jackson parses Java collections classes like List, Set or Arrays to JSON arrays.
Then according to required JSON structure list property is a such collection of DynamicJsonHelper objects you created. in Java class, List or Array is just your choice - use what is more suitable for you. I recommend to use a List rather than Array. Work with arrays in Java is not a good idea. :-)
So far you just created a Java class DynamicJsonHelper only for objects which must be in list property of JsonHolder object. What's left is to create that "JsonHolder" class and give that object to Jackson to serialize it into required JSON structure.
There are bunch of #Json annotations you can use to allow or not null or empty values, change property names, exclude Java class properties to be serialized and so, and so... All is up to you... good luck!

Change name of property while deserializing response in Java

JSON Response from API :
{
"result":[
{
"ResultType":"SUCCESS"
}
]
}
After Converting to ResultClass.class :
{
"result":[
{
"resultType":null
}
]
}
Expected Output After Converting to ResultClass.class :
{
"result":[
{
"resultType":"SUCCESS"
}
]
}
I am integrating with third party API.I want to change property name while deserializing .I have tried #JsonProperty on filed getter and setter.But the value is not reflected in field resultType.
ResultClass.java
#JsonProperty("result")
List<TestClass> result = new ArrayList<>();
public List<TestClass> getResult() {
return result;
}
public void setResult(List<TestClass> result) {
this.result = result;
}
TestClass.java
#JsonProperty("ResultType")
private String resultType;
public String getResultType() {
return resultType;
}
public void setResultType(String resultType) {
this.resultType = resultType;
}
Note : I have tried JsonObject and it is working fine.I am using HttpClient and HttpResponse for making request.Jackson Version : 2.5.0
2 Solutions are available:
1. Make case-insensitive deserializing
Add this feature on your object mapper:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
2. Serialize and deserialize with different property names
To change the name of the property ResultType to resultType, you should rather use both #JsonGetter and #JsonSetter:
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonSetter;
public class TestClass {
private String resultType;
#JsonGetter("resultType")
public String getResultType() {
return resultType;
}
#JsonSetter("ResultType")
public void setResultType(String resultType) {
this.resultType = resultType;
}
}

Jackson: Serialize comma separated string to json array

Currently I have form like below:
public class Form {
private String listOfItems;
public String getListOfItems() {
return listOfItems;
}
public void setListOfItems(String listOfItems) {
this.listOfItems= listOfItems;
}
}
For instanse listOfItems equals to the following string "1,2,3".
The goal is to serialize this form to following format:
{
"listOfItems": [1, 2, 3]
}
It would be good to know how to correctly do such thing? As I know it is possible to create some custom serializer then mark appropriate getter method with it, like this #JsonSerialize(using = SomeCustomSerializer).
But not sure whether it is correct approach, probably any default implementations already exist.
If you can edit your Form class:
public class Form {
private String listOfItems;
public String getListOfItems() {
return listOfItems;
}
public void setListOfItems(String listOfItems) {
this.listOfItems = listOfItems;
}
#JsonProperty("listOfItems")
public List<Integer> getArrayListOfItems() {
if (listOfItems != null) {
List<Integer> items = new ArrayList();
for (String s : listOfItems.split(",")) {
items.add(Integer.parseInt(s)); // May throw NumberFormatException
}
return items;
}
return null;
}
}
By default Jackson looks for getters for serializing. You can override this by using #JsonProperty annotation.
ObjectMapper mapper = new ObjectMapper();
Form form = new Form();
form.setListOfItems("1,2,3");
System.out.print(mapper.writeValueAsString(form));
Outputs:
{"listOfItems":[1,2,3]}

serialize json array into java objects

I have a JSON array like as shown below which I need to serialize it to my class. I am using Jackson in my project.
[
{
"clientId": "111",
"clientName": "mask",
"clientKey": "abc1",
"clientValue": {}
},
{
"clientId": "111",
"clientName": "mask",
"clientKey": "abc2",
"clientValue": {}
}
]
In above JSON array, clientValue will have another JSON object in it. How can I serialize my above JSON array into my java class using Jackson?
public class DataRequest {
#JsonProperty("clientId")
private String clientId;
#JsonProperty("clientName")
private int clientName;
#JsonProperty("clientKey")
private String clientKey;
#JsonProperty("clientValue")
private Map<String, Object> clientValue;
//getters and setters
}
I have not used jackson before so I am not sure how can I use it to serialize my JSON array into Java objects? I am using jackson annotation here to serialize stuff but not sure what will be my next step?
You can create a utility function shown below. You may want to change the Deserialization feature based on your business needs. In my case, I did not want to fail on unknown properties => (FAIL_ON_UNKNOWN_PROPERTIES, false)
static <T> T mapJson(String body,
com.fasterxml.jackson.core.type.TypeReference<T> reference) {
T model = null;
if(body == null) {
return model;
}
com.fasterxml.jackson.databind.ObjectMapper mapper =
new com.fasterxml.jackson.databind.ObjectMapper();
mapper.configure(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
false);
try {
model = mapper.readValue(body, reference);
} catch (IOException e) {
//TODO: log error and handle accordingly
}
return model;
}
You can call it using similar approach as shown below:
mapJson(clientValueJsonString,
new com.fasterxml.jackson.core.type.TypeReference<List<DataRequest>>(){});
You can try #JsonAnyGetter and #JsonAnySetter annotations with an inner class object. Also clientName should have type String, not int.
public class DataRequest {
private String clientId;
private String clientName;
private String clientKey;
private ClientValue clientValue;
//getters and setters
}
public class ClientValue {
private Map<String, String> properties;
#JsonAnySetter
public void add(String key, String value) {
properties.put(key, value);
}
#JsonAnyGetter
public Map<String,String> getProperties() {
return properties;
}
}

Categories

Resources