I have json from url. I need Convert This json to Model
{
"someField": 3,
"datesField": ["2017-08-19",
"2017-08-20",
"2017-08-26",
"2018-12-30"]
}
I create models for mapping
#Data
#NoArgsConstructor
private class Response{
#JsonProperty("someField")
private int someField;
#JsonProperty("datesField")
private DatesField datesField;
}
#Data
#NoArgsConstructor
private class DatesField{
private String[] strings;
}
try convert
ObjectMapper mapper = new ObjectMapper();
Dates dates = mapper.readValue(forObject, Response.class);
I get error when try convert:
Can not deserialize instance of packeg.DatesField out of START_ARRAY
token
The json attributed is incorrect according to the model. There is no array of datesField type but an array of strings within the datesField object.
Your object json equivalent shall be:
{
"someField": 3,
"datesField": {
"strings":["2017-08-19",
"2017-08-20",
"2017-08-26",
"2018-12-30"]
}
}
Or the other way, if you need to adapt to the json response, change your model as suggested by #xenteros to:
#Data
#NoArgsConstructor
private class Response{
#JsonProperty("someField")
private int someField;
#JsonProperty("datesField")
private String[] datesField;
}
Also, note that the java code to map the response should be changed from:
Dates dates = mapper.readValue(forObject, Response.class);
to
Response response = mapper.readValue(forObject, Response.class);
{
"someField": 3,
"datesField": ["2017-08-19",
"2017-08-20",
"2017-08-26",
"2018-12-30"]
}
is equivalent to
#Data
#NoArgsConstructor
private class Response{
#JsonProperty("someField")
private int someField;
#JsonProperty("datesField")
private String[] datesField;
}
You should rather parse the following json:
{
"someField": 3,
"datesField": {
"strings":
["2017-08-19",
"2017-08-20",
"2017-08-26",
"2018-12-30"]
}
}
Related
I have a JSON structured like:
{
"id" : "123",
"name" : [ {
"id" : "234",
"stuff" : [ {
"id" : "345",
"name" : "Bob"
}, {
"id" : "456",
"name" : "Sally"
} ]
} ]
}
I want to map to the following data structure:
Class01
#Getter
public class Class01{
private String id;
#JsonDeserialize(using = Class01HashMapDeserialize.class)
private ArrayList<Class02> name;
}
Class02
#Getter
public class Class02{
private String id;
private ArrayList<Class03> stuff;
}
Class03
#Getter
public class Class03{
private String id;
private String name;
}
In my main Method im using an ObjectMapper with objectMapper.readValue(jsonString,new TypeReference<ArrayList<Class02>>(){}) to map this JSON to my Class01. This Class successfully deserealizes the Class02-array into the name array.
When it comes to the second array I don't know how to further deserialize as I am not able to access the json text from the class02 stuff entry.
#Override
public ArrayList<Class02> deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException {
ArrayList<Class02> ret = new ArrayList<Class02>();
ObjectCodec codec = parser.getCodec();
TreeNode classes02 = codec.readTree(parser);
if (classes02.isArray()) {
for (JsonNode class02 : (ArrayNode) classes02) {
if(classe02.get("stuff").isArray()){
ObjectMapper objectMapper = new ObjectMapper();
ArrayList<Class03> classes03 = objectMapper.readValue(class02.get("stuff").asText(), new TypeReference<ArrayList<Class03>>(){});
}
ret.add(new Class02(class02.get("id").asText(), classes03));
}
}
return ret;
}
Why did you put a #JsonDeserialize annotation ? Jackson shall be able to deserialize it just fine without any custom mapping:
#Getter
public class Class01{
private String id;
private ArrayList<Class02> name;
}
Also in a first pass, I would generate the getters/setters/constructor manually for the 3 classes. There may be issues with Lombok & Jackson that you may want to solve later once you made the first version of the code works (Can't make Jackson and Lombok work together)
And your reader shall be more like:
ObjectMapper objectMapper = new ObjectMapper();
String text = ... //Your JSon
Class01 class01 = objectMapper.readValue(text, Class01.class)
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;
I have json like that:
{
"somethingElse": "foobar",
"snils": {
"number": "123"
}
}
And class:
#Data
public class Documents {
private String snilsNumber;
private String somethingElse;
}
Can I easily map json to my class with annotation or something else?
You can use '#JsonRootName'
#Data
#JsonRootName(value = "snils")
#JsonIgnoreProperties(unknown = true)
public class Documents {
private String number;
}
You can deserialise it using one extra update method with JsonProperty annotation.
class Documents {
private String snilsNumber;
private String somethingElse;
#JsonProperty("snils")
private void unpackSnils(Map<String, Object> brand) {
this.snilsNumber = (String) brand.get("number");
}
// getters, setters, toString
}
See also:
Jackson nested values
unwrap inner json object using jackson
I have an Entity class below with two String fields: name and description. The description field is to contain a raw JSON value e.g. { "abc": 123 }
#Getter
#Setter
public class Entity {
private String name;
#JsonRawValue
private String descriptionJson;
}
I've got simple test code below using Jackson to serialize and deserialize:
Entity ent = new Entity();
ent.setName("MyName");
ent.setDescriptionJson("{ \"abc\": 123 }");
// Convert Object to JSON string
String json = mapper.writeValueAsString(ent);
// Convert JSON string back to object
Entity ent2 = mapper.readValue(json, Entity.class);
When converting Object -> JSON the description string is nested because the #JsonRawValue is set:
{"name":"MyName","descriptionJson":{ "abc": 123 }}
However, when I call the Jackson mapper.readValue function to read the JSON string back into an entity object I get the exception:
com.fasterxml.jackson.databind.exc.MismatchedInputException:
Cannot deserialize instance of `java.lang.String` out of START_OBJECT token
at [Source: (String)"{"name":"MyName","descriptionJson":{ "abc": 123 }}"; line: 1, column: 36] (through reference chain: com.test.Entity["descriptionJson"])
Given that the #JsonRawValue annotation exists, how would you recommend marshalling the created JSON string back into to Entity object? Is there another annotation I'm missing?
Thanks
#JsonRawValue is intended for serialization-side only, but in this problem you can do like this:
#Getter
#Setter
public class Entity {
private String name;
#JsonRawValue
private String descriptionJson;
#JsonProperty(value = "descriptionJson")
public void setDescriptionJsonRaw(JsonNode node) {
this.descriptionJson = node.toString();
}
}
This problem is repeated with
How can I include raw JSON in an object using Jackson?.
For one of my requirements I used field type as Map to store Json as it is. This way I was able to read the nested JSOn as Map and when I serialize object to JSON, it came up correctly. Below is the example.
Entity.java
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.util.HashMap;
import java.util.Map;
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
public class Entity {
public int id=0;
public String itemName="";
public Map<String,String> owner=new HashMap<>();
}
Temp.java
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class Temp {
public static void main(String[] args){
ObjectMapper objectMapper= new ObjectMapper();
try {
Entity entity
=objectMapper.readValue(Temp.class.getResource("sample.json"), Entity.class);
System.out.println(entity);
String json=objectMapper.writeValueAsString(entity);
System.out.println(json);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Sample.json
{
"id": 1,
"itemName": "theItem",
"owner": {
"id": 2,
"name": "theUser"
}
}
You can use ObjectMapper from Jackson 2 as follows:
ObjectMapper mapper = new ObjectMapper();
String jsonStr = "sample json string"; // populate this as required
MyClass obj = mapper.readValue(jsonStr,MyClass.class)
try escaping the curly braces in the description json's value.
#JsonRawValue is intended only sor serializatio from docs:
Marker annotation that indicates that the annotated method or field should be serialized by including literal String value of the property as is, without quoting of characters.
To solve your problem you can try
public class Entity {
#Getter
#Setter
private String name;
private String descriptionJson;
#JsonRawValue
public String getDescriptionJson() {
return descriptionJson;
}
public void setJson(JsonNode node) {
this.descriptionJson = node.toString();
}
}
I have a JSON String called primarySkillStr :
[
{
"id": 3,
"roleIds": [
2
],
"rating": 2
}
]
I try to map it to an object as follows:
primarySkillList = mapper.readValue(primarySkillStr,
new TypeReference<List<PrimarySkillDTO>>() {});
But when Iam converting this to a List then the roleIds List is null.
Am I doing something wrong, or is there any other way?
This is my DTO
public class PrimarySkillDTO {
private Integer id;
private Integer rating;
private List<Integer> roleIds;
private String name;
}
I have the following annotations in the PrimarySkillDTO class
#Data
#Builder
#AllArgsConstructor
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
The problem is that your JsonNaming annotation requires snake_case and you are not using it.
To solve it
remove the annotation #JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
or, rename the variable in the JSON String to role_ids
SnakeCaseStrategy will map roleIds <--> role_ids, The following codes work for me:
ObjectMapper objectMapper = new ObjectMapper();
TypeReference<List<TestClass>> typeRef = new TypeReference<List<TestClass>>() {};
List<TestClass> testList = objectMapper.readValue(testStringObject, typeRef);