I am trying to map a String (with json values) to my POJO but getting a null when I do that.
Can I get some advivec on what I am doing wrong pls. They are matching up correctly from what I see.
I have the following String:
"{\"identifier_type\":\"TEST\",\"simple_construct_response\":[{\"identifier\":\"123451234512435\",\"customer_id\":\"\",\"trim_code\":\"DDD\",\"trim_reason_code\":\"\",\"simple_products\":[{\"product_name\":\"ABC_CPS_ABCD\",\"product_presentment_timestamp\":\"2019-02-28 06:07:20:383\"}]}]}"
It would conform to the following structure.
{
"identifier_type": "TEST",
"simple_construct_response": [
{
"identifier": "123451234512435",
"customer_id": "",
"trim_code": "DDD",
"trim_reason_code": "",
"simple_products": [
{
"product_name": "ABC_CPS_ABCD",
"product_presentment_timestamp": "2019-02-28 06:07:20:383"
}
]
}
]
}
This is my code where the output is null when I map.
String response = "{\"identifier_type\":\"TEST\",\"simple_construct_response\":[{\"identifier\":\"123451234512435\",\"customer_id\":\"\",\"trim_code\":\"DDD\",\"trim_reason_code\":\"\",\"simple_products\":[{\"product_name\":\"ABC_CPS_ABCD\",\"product_presentment_timestamp\":\"2019-02-28 06:07:20:383\"}]}]}";
ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MainResponse output = mapper.readValue(response, MainResponse.class); // this results in null
These are my POJOs to match above string.
#Getter
#Setter
public class MainResponse {
private String identifierType;
private List<SimpleConstructResponse> simpleConstructResponse;
}
#Getter
#Setter
public class simpleConstructResponse {
private String identifier;
private String customerId;
private String trimCode;
private String trimReasonCode;
private List<SimpleProduct> simpleProducts;
}
#Getter
#Setter
public class SimpleProduct {
private String productName;
private String productPresentmentTimestamp;
}
Instead of
ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
write following code
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
For the most part,
the fields in your JSON do not match the fields in your class.
Because of this,
you must identify the field mapping for Jackson.
Jackson provides a way to identify the field name in the JSON and to
associate it with a field in the Java class;
the #JsonProperty annotation.
Here is some example code:
#Getter
#Setter
public class MainResponse
{
#JsonProperty("identifier_type")
private String identifierType;
#JsonProperty("simple_construct_response")
private List<SimpleConstructResponse> simpleConstructResponseList;
}
#Getter
#Setter
public class SimpleConstructResponse
{
private String identifier;
#JsonProperty("customer_id")
private String customerId;
#JsonProperty("trim_code")
private String trimCode;
#JsonProperty("trim_reason_code")
private String trimReasonCode;
#JsonProperty("simple_products")
private List<SimpleProduct> simpleProducts;
}
#Getter
#Setter
public class SimpleProduct
{
#JsonProperty("product_name")
private String productName;
#JsonProperty("product_presentment_timestamp")
private String productPresentmentTimestamp;
}
Related
I have this API request payload containing some nested fields:
{
"myId": "studentOne",
"myFirstName": "joe",
"myLastName": "bloggs",
"demoPackages":
[{
"myparts": "https://example.com/myparts/a1234567-5d25-9gf1-23ua-45pb3874265l",
"myPackages": [
"https:/example.com/myPackages/0sk98926-939a-444a-95ta-8eb40125f7r1"
]
}
]
}
I have this corresponding request model DTO:
#Data
#AllArgsConstructor
#NoArgsConstructor
#Builder
public class DemoRequest {
private String myId;
private String myFirstName;
private String myLastName;
private ArrayList<DemoPackage> demoPackages;
#Data
#AllArgsConstructor
#NoArgsConstructor
#Builder
public class DemoPackage{
private String myparts;
private ArrayList myPackages;
}
}
Now, the challenge. When creating a builder object that holds the API request, I am lost as to how to pass the ArrayList fields. I tried this:
public Object createMyPayload(String myId, String myFirstName, String myLastName, ArrayList myparts, ArrayList myPackages) { //not too sure if I am passing myParts and myPackages correctly here
return DemoRequest.builder()
.myId(myId)
.myFirstName(myFirstName)
.myLastName(myLastName)
.releasePackages(myparts)
.releasePackages(myPackages)
.build();
When I call the createMyPayload() from another class to use the builder object, I am getting a compilation error which suggests that my ArrayList fields data type is wrong:
#When("I send a POST request to the endpoint (.*)$")
public void create(String endpoint, String myId, String myFirstName, String myLastName, ArrayList myparts, ArrayList myPackages) {
String id = "studentOne"
String myFirstName = "joe"
String myLastName = "bloggs"
String myParts = "https://example.com/myparts/a1234567-5d25-9gf1-23ua-45pb3874265l";
String myPackages = "https:/example.com/myPackages/0sk98926-939a-444a-95ta-8eb40125f7r1";
demoClass.post(createPayload.createMyPayload(myId, myFirstName, myLastName, myParts, myPackages), endpoint); // myParts and myPackages throw compilation error that data should be Arraylist but when I change to ArrayList, it's asking me to change back to String
How do I correctly pass myParts and myPackages to the lombok builder object and reuse them elsewhere?
This should work.
Note that I have used ArrayList & Array where [] would be better, but you mentioned API using ArrayList. Used List in declarations rather than ArrayList (because that's better practise)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class PackageBuilderDemo {
public static void main(String[] args) {
PackageBuilderDemo packageBuilderDemo = new PackageBuilderDemo();
packageBuilderDemo.createMyPayload("studentOne", "joe", "bloggs", "https://example.com/myparts/a1234567-5d25-9gf1-23ua-45pb3874265l", Arrays.asList(new String[] {"https:/example.com/myPackages/0sk98926-939a-444a-95ta-8eb40125f7r1"}));
}
public DemoRequest createMyPayload(String myId, String myFirstName, String myLastName, String myParts, List<String> myPackages) {
DemoPackage demoPackage = DemoPackage.builder().myparts(myParts).myPackages(myPackages).build();
List<DemoPackage> demoPackages = new ArrayList<>();
demoPackages.add(demoPackage);
return DemoRequest.builder()
.myId(myId)
.myFirstName(myFirstName)
.myLastName(myLastName)
.demoPackages(demoPackages)
.build();
}
}
#Data
#AllArgsConstructor
#NoArgsConstructor
#Builder
public class DemoRequest {
private String myId;
private String myFirstName;
private String myLastName;
private List<DemoPackage> demoPackages;
}
#Data
#AllArgsConstructor
#NoArgsConstructor
#Builder
public class DemoPackage{
private String myparts;
private List<String> myPackages;
}
I would like to know is there a way (probably using deserialiser) in Jackson to copy one attribute value to another object attribute the container has.
For example, documentId from the TestData class also needs to be persisted in the Details.documentId attribute.
json/TestData.json
{
"id": "1",
"documentId" : "234234",
"details" : {
"name": "test",
"lastName": "asdf"
}
}
#RequiredArgsConstructor(onConstructor_ = #Autowired)
#SpringBootTest(classes = ExampleMicroserviceApplication.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)
#ActiveProfiles("test")
public class TestDocumentId {
final ObjectMapper objectMapper;
#Value("classpath:json/TestData.json")
Resource testData;
#SneakyThrows
#Test
void testDocumentIdPresentInDetails() {
var data = objectMapper.readValue(testData.getFile(), TestData.class);
assertThat(data.documentId).isNotNull();
assertThat(data.getDetails().name).isNotNull();
assertThat(data.getDetails().documentId).isNotNull();
}
#Data
public static class TestData {
private String id;
private String documentId;
private Details details;
#Data
public static class Details {
private String documentId;
private String name;
private String lastName;
}
}
}
I'm trying to map specific JSON to my Java Model class. And am having trouble mapping it to the Java object.
I'm using fasterxml (jackson) to map JSON to my Java Model class below - CurrencyModel.java. This JSON have '[' at the beginning which it probably means that it is an array. I cannot map it into my class, CurrencyModel.java
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
class CurrencyModel {
protected List<Currencies> currencies;
protected List<CurrenciesRates> currenciesRates;
#Data
#NoArgsConstructor
#AllArgsConstructor
static class Currencies {
#JsonProperty("table")
private String table;
#JsonProperty("no")
private String no;
#JsonProperty("effectiveDate")
private String effectiveDate;
#JsonProperty("rates")
private ArrayList<CurrencyRatesModel> rates;
}
#Data
#NoArgsConstructor
#AllArgsConstructor
static class CurrenciesRates {
#JsonProperty("currency")
private String currency;
#JsonProperty("code")
private String code;
#JsonProperty("mid")
private String mid;
}
}
And having JSON below in String variable
[
{
"table": "A",
"no": "064/A/NBP/2013",
"effectiveDate": "2013-04-02",
"rates": [
{
"currency": "bat (Tajlandia)",
"code": "THB",
"mid": 0.1108
},
{
"currency": "dolar amerykański",
"code": "USD",
"mid": 3.2552
},
{
"currency": "dolar australijski",
"code": "AUD",
"mid": 3.4048
}
]
}
]
I'm trying to run this code using:
ObjectMapper objectMapper = new ObjectMapper();
final String output = "[{\"table\": \"A\", \"no\": \"064/A/NBP/2013\",\"effectiveDate\": \"2013-04-02\",\"rates\": [{\"currency\": \"bat (Tajlandia)\",\"code\": \"THB\",\"mid\": 0.1108},{\"currency\": \"dolar amerykański\",\"code\": \"USD\",\"mid\": 3.2552},{\"currency\": \"dolar australijski\",\"code\": \"AUD\",\"mid\": 3.4048}]}]";
List<CurrencyModel> currencyModelList = Arrays.asList(objectMapper.readValue(output, CurrencyModel.class));
objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
System.out.println(currencyModelList.toArray());
which results in error:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `` out of START_ARRAY token
I see problem with your java class. I have executed your input json and come with mentioned below java class mapping.
#Data
#NoArgsConstructor
#AllArgsConstructor
public class CurrencyModel {
#JsonProperty("table")
private String table;
#JsonProperty("no")
private String no;
#JsonProperty("effectiveDate")
private String effectiveDate;
#JsonProperty("rates")
private ArrayList<CurrenciesRates> rates;
#Data
#NoArgsConstructor
#AllArgsConstructor
static class CurrenciesRates {
#JsonProperty("currency")
private String currency;
#JsonProperty("code")
private String code;
#JsonProperty("mid")
private String mid;
}
}
And your main class,
ObjectMapper objectMapper = new ObjectMapper();
final String output = "[{\"table\": \"A\", \"no\": \"064/A/NBP/2013\",\"effectiveDate\": \"2013-04-02\",\"rates\": [{\"currency\": \"bat (Tajlandia)\",\"code\": \"THB\",\"mid\": 0.1108},{\"currency\": \"dolar amerykański\",\"code\": \"USD\",\"mid\": 3.2552},{\"currency\": \"dolar australijski\",\"code\": \"AUD\",\"mid\": 3.4048}]}]";
List<CurrencyModel> myObjects = objectMapper.readValue(output, new TypeReference<List<CurrencyModel>>() {
});
Your json contains list of object. So use TypeReference
ObjectMapper objectMapper = new ObjectMapper();
final String output = "[{\"table\": \"A\", \"no\": \"064/A/NBP/2013\",\"effectiveDate\": \"2013-04-02\",\"rates\": [{\"currency\": \"bat (Tajlandia)\",\"code\": \"THB\",\"mid\": 0.1108},{\"currency\": \"dolar amerykański\",\"code\": \"USD\",\"mid\": 3.2552},{\"currency\": \"dolar australijski\",\"code\": \"AUD\",\"mid\": 3.4048}]}]";
objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
List<CurrencyModel> currencyModelList = objectMapper.readValue(output, new TypeReference<List<CurrencyModel.Currencies>>(){});
System.out.println(currencyModelList);
JSON FORMAT:
[
{
"0":
{
"cast":"",
"showname":"woh pagle",
"type":"Episodes"
},
"video":[
{
"src":"video.mp4"
},
{
"DRM":"False"
}
]
}
]
Here problem is I am getting below exception:
org.codehaus.jackson.map.JsonMappingException: Can not deserialize
instance of java.util.ArrayList out of START_OBJECT token at [Source:
java.io.StringReader#1c9ca1; line: 1, column: 55617] (through
reference chain:
com.apalya.myplex.valueobject.ThirdPartyContentDetailsArray["video"])
My pojo classes are :
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonProperty("0")
private ThirdPartySubContentDetails subContent;
#JsonProperty("video")
private List<ThirdPartySubContentVideoInfo> video;
My Sub class pojo is :
private String src;
#JsonIgnore
#JsonProperty("DRM")
private String drm;
Please help me to write a pojo for that video list.
Your json starts as an array and not as an Object. The important part to change is how the Objectmapper should generate your json. For returning a List you need to do it this way:
List<FirstJson> jsonList = mapper.readValue(json, new TypeReference<List<FirstJson>>(){});
Here is my short working test I implement locally:
public static void main(String[] args) {
String json = "[{\"0\":{\"cast\":\"\",\"showname\":\"wohpagle\",\"type\":\"Episodes\"},\"video\":[{\"src\":\"video.mp4\"},{\"DRM\":\"False\"}]}]";
ObjectMapper mapper = new ObjectMapper();
List<FirstJson> jsonList = mapper.readValue(json, new TypeReference<List<FirstJson>>(){});
System.out.println(jsonList.toString());
}
The first part of your JsonArray in Pojo.(Named it FirstJson)
public class FirstJson{
#JsonProperty("0")
private FirstJson subContent;
private String cast;
private String showname;
private String type;
#JsonProperty("video")
private List<Video> videos;
//getter/setter
And the Video Pojo:
public class Video {
private String src;
#JsonProperty("DRM")
private String drm;
//getter/setter
Just a sidenote: If you declare your pojos in the same class file, the classes should be static. public static class FirstJson
According to the JSON structure described in the question, the following should be the POJOs:
public class MainPojo
{
#JsonProperty("0")
private ThirdPartySubContentDetails subContent;
#JsonProperty("video")
private List<ThirdPartySubContentVideoInfo> video;
// Getters and Setters for subContent and video
}
class ThirdPartySubContentDetails
{
private String cast;
private String showName;
private String type;
// Getters and Setters for cast, showName and type
}
#JsonIgnoreProperties(ignoreUnknown = true)
class ThirdPartySubContentVideoInfo
{
#JsonProperty("src")
private String src;
#JsonProperty("DRM")
private String drm;
// Getters and Setters for src and drm
}
You should call the deserializer method as follows:
List<MainPojo> list = new ObjectMapper().readValue(json, new TypeReference<List<MainPojo>>(){});
I want to deserialize the following JSON object:
{
"id":"001",
"module_name":"Users",
"name_value_list":
{
"user_name": {"name":"user_name", "value":"admin"},
"full_name": {"name":"full_name", "value":"Lluís Pi"},
"city": {"name":"full_name", "value":"Barcelona"},
"postal_code": {"name":"postal_code", "value":"08017"},
...
}
}
into some Java object like this:
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
public class UserEntry
{
private String id;
private String moduleName;
private Person nameValueList;
public String getId()
{
return id;
}
public String getModuleName()
{
return moduleName;
}
public Person getPerson()
{
return nameValueList;
}
}
where Person is the following class:
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
class Person
{
private String userName;
private String fullName;
private String city;
private String postalCode;
}
using Jackson but I get a deserialization error.
If I change the type of field nameValueList to a Map all the deserialization process goes with no problem and I get a map where the key is the "name" value and the value is the "value" value.
So my question is: is there any simple, or no so simple, way to deserialize this kind of JSON object to a Java Pojo with properties prop_1, prop_2, prop_3and prop_4?
{
"name_value_list":
{
"prop_1": {"name":"prop_1", "value":"value_1"},
"prop_2": {"name":"prop_2", "value":"value_2"},
"prop_3": {"name":"prop_3", "value":"value_3"},
"prop_4": {"name":"prop_4", "value":"value_4"},
...
}
}
Not very simple and not very clean. However you can do it by implementing a any setter field for the JSON attributes in the Person class which don't match any attribute on your UserEntry POJO.
#JsonAnySetter
public void putUserField(String userKey, Map<String, String> userValue)
throws NoSuchFieldException {
String actualFieldName = getActualFieldName(userKey);
Field field = this.getClass().getDeclaredField(actualFieldName);
field.setAccessible(true);
ReflectionUtils.setField(field, this, userValue.get("value"));
}
private String getActualFieldName(String userKey) {
return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, userKey);
}
In addition to that, I had to change the Jackson attributes for the Person class to
#JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY,
getterVisibility = JsonAutoDetect.Visibility.NONE)
for it to work for attributes like "city" which don't need any name transformation because jackson tries to directly set the field which fails.