Not able to convert Json String to Java objects - java

I am unable to convert the given Json String to java Object
Validated the Json format, it is correct.
#JsonIgnoreProperties(ignoreUnknown = true)
public class DevPol {
private String id;
private Header header;
//Setters and Getters
}
#JsonIgnoreProperties(ignoreUnknown = true)
public class Header {
private String name;
private String lastUpdate;
private int priority;
private boolean active;
//Setters and Getters
}
import com.fasterxml.jackson.databind.ObjectMapper;
public class ConvertJsonToJava {
static String apiResult = "[ {\"Id\":\"5899503ad06f7f0008817430\", \"Header\":{ \"name\":\"ClCol\"," +
" \"lastupdate\":\"2017-02-07T04:42:34.654Z\", \"priority\":1, \"active\":true } }," +
" { \"Id\":\"5899503ad06f7f0008817431\",\"Header\":{ \"name\":\"SysPol\"," +
" \"lastupdate\":\"2017-02-07T04:42:34.659Z\", \"priority\":2, \"active\":true } }]";
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
DevPol[] devPOlArr = mapper.readValue(apiResult, DevPol[].class);
for(DevPol devPol: devPOlArr) {
System.out.println(devPol.getId());
}
}
}
I expected the output to be Id values but,the result is
null
null

The issue is upper-case letters in json field names and java class fields.
If it is possible rename 'Id' -> 'id' in json and java. Otherwise you should add json property names to java fields:
public class DevPol {
#JsonProperty("Id")
private String Id;
#JsonProperty("Header")
private Header Header;
//Setters and Getters
}

Related

Creating complex JSON payload from Java Pojo Jackson

I want to create below JSON payload
{
"maxResults":3,
"counter":0,
"customerParameters":{
"filters":[
{
"name":"customerId",
"operator":"=",
"value":["hello"]
}
]
},
"dealerParameters":[
{
"name":"club"
},
{
"name":"token"
}
]
}
Coded so far:
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"maxResults",
"counter",
"customerParameters",
"dealerParameters"
})
public class CustomerModel {
#JsonProperty("maxResults")
private Integer maxResults;
#JsonProperty("counter")
private Integer counter;
#JsonProperty("customerParameters")
private CustomerParameters customerParameters;
#JsonProperty("dealerParameters")
private List<DealerParameter> dealerParameters = null;
#JsonProperty("customerParameters")
public CustomerParameters getCustomerParameters() {
return customerParameters;
}
#JsonProperty("customerParameters")
public void setCustomerParameters(CustomerParameters customerParameters) {
this.customerParameters = customerParameters;
}
#JsonProperty("dealerParameters")
public List<DealerParameter> getDealerParameters() {
return dealerParameters;
}
#JsonProperty("dealerParameters")
public void setDealerParameters(List<DealerParameter> dealerParameters) {
this.dealerParameters = dealerParameters;
}
// Getter/Setter for other params
}
CustomerParameters.java
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"filters"
})
public class CustomerParameters {
#JsonProperty("filters")
private List<Filter> filters = null;
// Setter and Getter for filters parameter
}
DealerParameters.java
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"name"
})
public class DealerParameter {
#JsonProperty("name")
private String name;
#JsonProperty("name")
public String getName() {
return name;
}
#JsonProperty("name")
public void setName(String name) {
this.name = name;
}
}
Filter.java
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"name",
"operator",
"value"
})
public class Filter {
#JsonProperty("name")
private String name;
#JsonProperty("operator")
private String operator;
#JsonProperty("value")
private List<String> value = null;
#JsonProperty("value")
public List<String> getValue() {
return value;
}
#JsonProperty("value")
public void setValue(List<String> value) {
this.value = value;
}
// Setter and Getter for other properties
}
Missing Part:
#Controller
public class TestContoller {
RestTemplate restTemplate;
Should I instantiate each pojo class with new operator as below and set all required parameters ? or any other approach of creating JSON payload?
CustomerModel customerModel= new CustomerModel();
customerModel.setMaxResults(1);
Filter filter= new Filter();
filter.setName("customerID");
filter.setOperator("-");
filter.setValue(Arrays.asList("club"));
CustomerParameters customerParameters = new CustomerParameters();
customerParameters.setFilters(Arrays.asList(filter));
customerModel.setCustomerParameters(customerParameters);
For DealerParameter class, I want to create multiple objects with same key different value(see the json payload I mentioned above). Below code creates only one object "name":"dealerId"
DealerParameter dealerParameter = new DealerParameter();
dealerParameter.setName("dealerId");
customerModel.setDealerParameters(dealerParameter);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.writeValueAsString(customerModel);
restTemplate.exchange(todo); // restful service call
}
you are already using "ObjectMapper", And ObjectMapper has readValue() method. By using readValue() method you can populate all data at a time like below:--
ObjectMapper objectMapper = new ObjectMapper();
//populating data from json string to POJO
CustomerModel customerModel = objectMapper.readValue(<json String>,CustomerModel.class);
System.out.println(objectMapper.writeValueAsString(customerModel); // print all data

Why are some of the variables in POJO equal to null after converting JSON RESTful Webservice?

I am consuming a RESTful webservice that returns a JSON payload. I can successfully consume the RESTful webservice and manage to populate some of the POJO attributes with JSON data. However, some other attributes are null when they are supposed to contain a value. How can I ensure that there are no more nulls?
I have defined 4 POJO classes. I have so far debugged by systematically by testing the variables for each class. This is using Springboot 2.2.0 and Jackson-databind.
The JSON schema I am trying to consume:
{
"items":[
{
"timestamp":"2019-09-18T16:42:54.203Z",
"carpark_data":[
{
"total_lots":"string",
"lot_type":"string",
"lots_available":"string"
}
]
}
]
}
For the above, I defined 4 classes:
public class Response {
#JsonProperty
private List<items> i;
#JsonIgnoreProperties(ignoreUnknown = true)
public class items {
private String timestamp;
private List<carpark_data> cpd;
#JsonIgnoreProperties(ignoreUnknown = true)
public class carpark_data {
private List<carpark_info> cpi;
private String carpark_number;
private String update_datetime;
#JsonIgnoreProperties(ignoreUnknown = true)
public class carpark_info {
private int total_lots;
private String lot_type;
private int lots_available;
When I run the below in Spring boot Main: I get null. Is my POJO modeling OK?
Response resp = restTemplate.getForObject("")
c = resp.getItems().get(0).getCarpark_data().get(0);
log.info("The last update time for the car park data = " +
c.getUpdateDatetime());
Your model does not fit to JSON payload. If we assume that JSON payload has a structure like below:
{
"items": [
{
"timestamp": "2019-09-18T16:42:54.203Z",
"carpark_data": [
{
"total_lots": "1000",
"lot_type": "string",
"lots_available": "800"
}
]
}
]
}
We can deserialise it as below:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.util.List;
public class JsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
ObjectMapper mapper = new ObjectMapper();
Response response = mapper.readValue(jsonFile, Response.class);
System.out.println(response.getItems().get(0).getData().get(0));
}
}
class Response {
private List<Item> items;
//getters, setters, toString
}
class Item {
private String timestamp;
#JsonProperty("carpark_data")
private List<CarParkInfo> data;
//getters, setters, toString
}
class CarParkInfo {
#JsonProperty("total_lots")
private int totalLots;
#JsonProperty("lot_type")
private String lotType;
#JsonProperty("lots_available")
private int lotsAvailable;
//getters, setters, toString
}
Above code prints:
CarParkInfo{totalLots=1000, lotType='string', lotsAvailable=800}
Hope you find the solution.
It is in POJO, you need to check the fieldName and object structure.
Seeing the Json above, your response model returns list of items and in each item you have list of carpark_data. So, basic modelling should be like this. And you can include respective setter and getter.
public class Response {
#JsonProperty
private List<items> items;
#JsonIgnoreProperties(ignoreUnknown = true)
public class items {
private String timestamp;
private List<carpark_data> carpark_data;
#JsonIgnoreProperties(ignoreUnknown = true)
public class carpark_data {
private int total_lots;
private String lot_type;
private int lots_available;
}
You need to have fields name in POJO class same in the Json response or you can set JsonProperty for that field. Like this
#JsonProperty("items")
private List<items> i;
#JsonProperty("carpark_data")
private List<carpark_data> cpd;

Jackson - Deserialize empty String Member to null

I like to deserialize with Jackson an empty String member ("") to null. The Deserialization Feature "ACCEPT_EMPTY_STRING_AS_NULL_OBJECT" can for this unfortunately not be used (see link).
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonInclude(Include.NON_NULL)
public class Supplier {
private Integer id;
private String name;
private String image;
private String link;
private String description;
}
So after deserialization of the following JSON String the string members "link" and "image" should be null and not "".
{"id":37,"name":"Life","image":"","link":"","description":null}
I am looking for a way to write an own deserializer which can be used for String members of a POJO. Is there a way to achieve this? I am using faster Jackson 2.6.0.
The custom deserializer can be done as follows in Jackson 2.6.0.
public class SupplierDeserializer extends JsonDeserializer<Supplier> {
#Override
public Supplier deserialize(JsonParser jp, DeserializationContext context) throws IOException, JsonProcessingException {
Supplier sup = new Supplier();
JsonNode node = jp.readValueAsTree();
sup.setId(node.get("id").asInt());
sup.setDescription(node.get("description").asText());
String image = node.get("image").asText();
if("".equals(image)) {
image = null;
}
sup.setImage(image);
String link = node.get("link").asText();
if("".equals(link)) {
link = null;
}
sup.setLink(link);
sup.setName(node.get("name").asText());
return sup;
}
}
Register the custom deserialiser with the Supplier class
#JsonDeserialize(using = SupplierDeserializer.class)
public class Supplier {
private Integer id;
private String name;
private String image;
private String link;
private String description;
// getters and setters
}
Call the ObjectMapper class to parse the JSON data
String jsonData = "{\"id\":37,\"name\":\"Life\",\"image\":\"\",\"link\":\"\",\"description\":null}";
Supplier sup = new ObjectMapper().readValue(jsonData, Supplier.class);

How can I unwrap a specific field in a JSON using Jackson?

I have a JSON payload that looks like this:
{
"id": 32,
"name": "[Sample] Tomorrow is today, Red printed scarf",
"primary_image": {
"id": 247,
"zoom_url": "www.site.com/in_123__14581.1393831046.1280.1280.jpg",
"thumbnail_url": "www.site.com/in_123__14581.1393831046.220.290.jpg",
"standard_url": "www.site.com/in_123__14581.1393831046.386.513.jpg",
"tiny_url": "www.site.com/in_123__14581.1393831046.44.58.jpg"
}
}
Can I unwrap a specific field and discard all the others? In other words, can I bind this directly to a POJO like this:
public class Product {
private Integer id;
private String name;
private String standardUrl;
}
There are lots of ways. Do you need to deserialize, serialize or both?
One way to deserialize would be to use a creator method that takes the image as a tree node:
public static class Product {
private Integer id;
private String name;
private String standardUrl;
public Product(#JsonProperty("id") Integer id,
#JsonProperty("name") String name,
#JsonProperty("primary_image") JsonNode primaryImage) {
this.id = id;
this.name = name;
this.standardUrl = primaryImage.path("standard_url").asText();
}
}
The creator doesn't have to be a constructor, you could have a static method that is only used for Jackson deserialization.
You'd have to define a custom serializer to reserialize this, though (e.g. a StdDelegatingSerializer and a converter to wrap the string back up as an ObjectNode)
There are different ways to skin this cat, I hope you can use Jackson 2 for this, since it offers great ways to deserialize Json data, one of my favorites deserialization features is the one I'll show you here (using Builder Pattern) because allows you to validate instances when they are being constructed (or make them immutable!). For you this would look like this:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.util.Map;
#JsonDeserialize(builder = Product.Builder.class)
public class Product {
private Integer id;
private String name;
private String standardUrl;
private Product(Builder builder) {
//Here you can make validations for your new instance.
this.id = builder.id;
this.name = builder.name;
//Here you have access to the primaryImage map in case you want to add new properties later.
this.standardUrl = builder.primaryImage.get("standard_url");
}
#Override
public String toString() {
return String.format("id [%d], name [%s], standardUrl [%s].", id, name, standardUrl);
}
#JsonIgnoreProperties(ignoreUnknown = true)
public static class Builder {
private Integer id;
private String name;
private Map<String, String> primaryImage;
public Builder withId(Integer id) {
this.id = id;
return this;
}
public Builder withName(String name) {
this.name = name;
return this;
}
#JsonProperty("primary_image")
public Builder withPrimaryImage(Map<String, String> primaryImage) {
this.primaryImage = primaryImage;
return this;
}
public Product build() {
return new Product(this);
}
}
}
To test it I created this class:
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
String serialized = "{" +
" \"id\": 32," +
" \"name\": \"[Sample] Tomorrow is today, Red printed scarf\"," +
" \"primary_image\": {" +
" \"id\": 247," +
" \"zoom_url\": \"www.site.com/in_123__14581.1393831046.1280.1280.jpg\"," +
" \"thumbnail_url\": \"www.site.com/in_123__14581.1393831046.220.290.jpg\"," +
" \"standard_url\": \"www.site.com/in_123__14581.1393831046.386.513.jpg\"," +
" \"tiny_url\": \"www.site.com/in_123__14581.1393831046.44.58.jpg\"" +
" }" +
" }";
ObjectMapper objectMapper = new ObjectMapper();
try {
Product deserialized = objectMapper.readValue(serialized, Product.class);
System.out.print(deserialized.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
The output is (using the override toString() method in Product:
id [32], name [[Sample] Tomorrow is today, Red printed scarf], standardUrl [www.site.com/in_123__14581.1393831046.386.513.jpg].
There are two ways to get the response you required. For both methods, we are going to use JsonView.
Create two types of JsonView:
public interface JViews {
public static class Public { }
public static class Product extends Public { }
}
First method
#JsonView(JViews.Public.class)
public class Product {
private Integer id;
private String name;
#JsonIgnore
private Image primaryImage;
#JsonView(JViews.Product.class)
public String getStandardUrl{
return this.primaryImage.getStandardUrl();
}
}
Second way
Using Jackson's #JsonView and #JsonUnwrapped together.
#JsonView(JViews.Public.class)
public class Product {
private Integer id;
private String name;
#JsonUnwrapped
private Image primaryImage;
}
public class Image {
private String zoomUrl;
#JsonView(JViews.Product.class)
private String standardUrl;
}
#JsonUnwrapped annotation flattens your nested object into Product object. And JsonView is used to filter accessible fields. In this case, only standardUrl field is accessible for Product view, and the result is expected to be:
{
"id": 32,
"name": "[Sample] Tomorrow is today, Red printed scarf",
"standard_url": "url"
}
If you flatten your nested object without using Views, the result will look like:
{
"id": 32,
"name": "[Sample] Tomorrow is today, Red printed scarf",
"id":1,
"standard_url": "url",
"zoom_url":"",
...
}
Jackson provided #JsonUnwrapped annotation.
See below link:
http://jackson.codehaus.org/1.9.9/javadoc/org/codehaus/jackson/annotate/JsonUnwrapped.html

JSON parsing through GSON returns null values

I am trying to read the values of a JSON output.
This is the JSON output:
{"nameOfSummoner":{"id":56529189,"name":"test","profileIconId":550,"summonerLevel":30,"revisionDate":1422110739000}}
And with the following code I am trying to read it:
final Connector connector = new Connector();
String response = connector.connect("link"); // (Returns a String value of the JSON)
final Gson gson = new Gson();
final Summoner summoner = gson.fromJson(response, Summoner.class); //Summoner is a model class
System.out.println(summoner);
Summoner class:
public class Summoner {
private String name;
private long profileIconId;
private long summonerLevel;
private long revisionDate;
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public long getProfileIconId() {
return profileIconId;
}
public void setProfileIconId(final long profileIconId) {
this.profileIconId = profileIconId;
}
public long getSummonerLevel() {
return summonerLevel;
}
public void setSummonerLevel(final long summonerLevel) {
this.summonerLevel = summonerLevel;
}
public long getRevisionDate() {
return revisionDate;
}
public void setRevisionDate
(long revisionDate) {
this.revisionDate = revisionDate;
}
#Override
public String toString() {
return "Summoner{" +
"name='" + name + '\'' +
", profileIconId=" + profileIconId +
", summonerLevel=" + summonerLevel +
", revisionDate=" + revisionDate +
'}';
}
}
And I get the following output on the console:
Summoner{name='null', profileIconId=0, summonerLevel=0, revisionDate=0}
I have sadly no idea why this happens. Any help I get is appreciated. I am fairly sure it has to do with the JSON output that "nameOfSummoner" is on top and maybe that's why it does not read what is below.
As mentioned by #PeterMmm , your input is a map with 1 key-value pair.
You need to Create another POJO with Summoner object as attribute:
public class Sample {
private Summoner nameOfSummoner;
//getters and setters
}
and then try parsing. Or, you could create a Map and parse.
Map<String, Summoner> responseObj = new HashMap<String, Summoner>();
responseObj= gson.fromJson(response, responseObj.class);
Summoner obj = responseObj.get("nameOfSummoner");
You will also need to have "id" attribute in Summoner class I believe, else gson will throw an exception.

Categories