Desirialization does not work when there are multiple nodes available at same level as value provided in the JsonRootName
Note:
Wrapper is configured with following:
objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
Class:
#NoArgsConstructor
#AllArgsConstructor
#Getter
#Setter
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonRootName(value = "response")
public class UserProfile {
String name;
String link;
}
Input JSON (which works):
{
"response": {
"name": "User one:",
"link": "Some Link"
}
}
Input JSON (which does not work)
{
"response": {
"name": "User one:",
"link": "Some Link"
},
"apiVersion" : 1.0
}
Adding a wrapper for with fields response and apiVersion wouls solve this problem which would defeat the purpose of using tag JsonRootName
How to deserialize when there is more than one field at root level (without using another wrapper class) ?
Related
I have a json
{
"params": [
{
"key": "path",
"options": {
"string": {
"prefix": "test_pref"
}
},
"default": {
"url": ""
}
}
]}
I have the following POJO class, where i want to map inner objects like option.string.prefix in json to prefix in Params POJO class.
#Data
#Accessors(chain = true)
public class Data {
private List<Params> params;
}
#Data
#Accessors(chain = true)
public class Params {
private String key;
#JsonProperty("options.string.prefix")
private String prefix;
#JsonProperty("default.url")
private String url;
}
Is there any Jackson annotation that helps me do this without #JsonProperty?
The is #JsonGetter which is an alternative to #JsonProperty You can read a very nice article on the topic here: Jackson Annotation Examples
I tried multiple pattern , but still no success how can I create JSON Array object with nested JSON object similar like below
{
"deduction": [
{
"id": "50258779",
"amount": {
"value": 13.24,
"currency": "INR"
},
"transfer": "DEPOSIT",
"fund": "RL",
"description": "TD description",
"code": "codeNumber"
},
{
"id": "50258779",
"amount": {
"value": 13.24,
"currency": "INR"
},
"transfer": "DEPOSIT",
"fund": "RL",
"description": "TD description",
"code": "codeNumber"
}
]
}
I had generated Class to build this request schema :
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
#Builder
#Getter
#Setter
#JsonInclude(JsonInclude.Include.NON_EMPTY)
public class Transf{
private List<Deduction> deduction;
#Builder
#Getter
#Setter
public class Deduction {
private Amount amount;
private String transfer;
private String code;
private String fund;
private String description;
private Integer id;
}
#Builder
#Getter
#Setter
public class Amount {
private String currency;
private Double value;
}
}
Trying to create json request body to be send using rest assured
public Transf trans()
{
return Transf.builder()
.deduction(Transf.Deduction.builder().transfer("")).build();
}
But getting syntax error on this , need to know how can I make this work
Instead of
Transf.Deduction.builder().transfer("")
you need to have
Transf.Deduction.builder().transfer("").build()
First, you define private List<Deduction> deduction; --> you will supply List.
Second, to make builder work, you have to call .build()
public Transf trans() {
return Transf.builder()
.deduction(Arrays.asList(Transf.Deduction.builder().transfer("").build()))
.build();
}
I am trying to ignore a specified field from a list during deserialization. I am not sure how do i do that for a field that sits inside a list. Below is my json and response class
Sample json
{
"key": {
"rowKey": "123"
},
"names": [
{
"firstName": "JON ",
"firstNameFormatted": "JON"
}
]
}
Response class
#AllArgsConstructor
#NoArgsConstructor
#Getter
#Setter
#ToString
public class Data {
private Map<String,Object> key;
private List<Map<String,Object>> names;
}
Here i would like to ignore
firstNameFormatted
from my json response but i am not sure how to do that using jackson for a field that is inside a list ?
Jackson has a solution for that. Simply use #JsonIgnore
You can see it in the example below
#JsonIgnore
public String getPassword() {
return password;
}
Now the password information won’t be serialized to JSON.
Also you can try with #JsonIgnoreProperties
I wonder what's the recommended way to generate POJOs for Json schemas with "anyOf" fields?
For example, given the following json schemas:
hobby.json
{
"anyOf": [
{ "type": {"$ref": "./exercise.json" } },
{ "type": {"$ref": "./music.json" } }
]
}
exercise.json
{
"type": "object"
"properties" {
"hobbyType": {"type": "string"}
"exerciseName": { "type": "string" },
"timeSpent": { "type": "number" },
"place": { "type": "string" }
}
}
music.json
{
"type": "object"
"properties" {
"hobbyType": {"type": "string"}
"instrument": { "type": "string" },
"timeSpent": { "type": "number" }
}
}
How could I generate a POJO for Hobby.java with Jackson?
I think there are two approaches that seem natural:
One would be to generate a class hierarchy Hobby with the common field timeSpent and Music / Exercise being subclasses with their specific fields.
The other would be to "union" the fields into a single class Hobby.
Both are semantically incorrect meaning that you can come up with cases where JSON schema validates correctly but Jackson throws an error or the information is missing in the POJO due to an omitted field.
So I think the best approach here would be to resort to Map<String, Object> instead of pojos.
So for example if a Person has a hobby the Person POJO could be:
class Person {
String name;
...
Map<String, Object> hobby;
or List<Map<String, Object> hobbies> if one can have multiple hobbies.
The approach I ended up taking is using polymorphic marshaling/unmarshaling functionality provided by Jackson.
Specifically -
Make hobby to be an interface and annotate it with #JsonTypeInfo and #JsonSubTypes
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
property = "hobbyType",
include = JsonTypeInfo.As.EXISTING_PROPERTY,
visible = true
)
#JsonSubTypes({
#Type(value = Exercise.class, name = "exercise"),
#Type(value = Music.class, name = "music")
})
public interface Hobby {
}
Create Exercise.java and Music.java that implements this interface
#Builder
#Data
#AllArgsConstructor
public class Exercise implements Hobby {
#JsonProperty("hobbyType")
#Builder.Default
#NonNull
private final String hobbyType = "exercise";
#JsonProperty("exerciseName")
private String exerciseName;
#JsonProperty("place")
private String place;
//... (other fields)
}
Use Hobby for serialization and deserialization.
// create a Hobby object
Hobby exercise = Exercise.builder().exerciseName("swimming").place("swimmingPool").build();
// serialization
String serializedHobby = new ObjectMapper.writeValueAsString(exercise)
/**
serializedHobby looks like this ->
{
"hobbyType": "exercise",
"exerciseName": "swimming",
"place": "swimmingPool"
}
*/
// deserialization
Hobby deserializedObject = new ObjectMapper.readValue(jsonString, Hobby.class)
// deserializedObject.getClass() would return Exercise.java or Music.java based on the hobbyType
Ref: https://www.baeldung.com/jackson-inheritance
I have the following sample fragment of JSON I am trying to deserialize.
{
"total": 2236,
"issues": [{
"id": "10142",
"key": "ID-2",
"fields": {
"attachment": [{
"id": "11132"
}]
}
}]
}
I can deserialize the data up to id and key, but cannot deserialize attachments that is in fields. My attachment class is always null
Here's my code.
Response.java
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
public class Response {
#JsonProperty
private int total;
#JsonProperty
private List<Issue> issues;
}
Issue.java
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
public class Issue {
#JsonProperty
private int id;
#JsonProperty
private String key;
#JsonProperty
private Fields fields;
}
Fields.java
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
public class Fields {
#JsonProperty
private Attachments attachment;
}
Attachments.java
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
public class Attachments {
#JsonProperty
private List<Attachment> attachment;
}
Attachments.java
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
public class Attachment {
#JsonProperty
private String id;
}
In your JSON, attachment is an array, not an object.
You don't need an Attachments class, just modify Fields this way:
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
public class Fields {
#JsonProperty
private List<Attachment> attachment;
}
Think of each variable in your Java classes as corresponding to an attribute in the JSON. "Attachments" is not in the JSON file. You should be able to remove it and change the variable definition in the Fields class.
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
public class Fields {
#JsonProperty
private List<Attachment> attachment;
}
If you don't want to change class structure then, you can modify JSON.
In attachment, you need to add again an attachment.
JSON would be like below.
{
"total":2233,
"issues":[
{
"id":"13598",
"key":"ID-2368",
"fields":{
"attachment":{
"**attachment**":[
{
"id":"11122"
}
]
}
}
}
]
}