I have a JSON that looks like this
{
Name: "Jhon",
Age: 28,
Children:[{..},{..}]
}
I have created two entities Person and Children, and a wrapper Payload
class Payload{
Person A;
Children x[];
}
I want to do something like this
Payload payload = mapper.readValue(request, Payload.class);
The fields are not being mapped correctly, since name and age fields are at root.
A JSON like below would have worked in this scenario but I cannot change the JSON neither can I place the name and age fields inside Payload. I find out about #JsonRootName annotation but not sure how or will it work or not.
{
Person: { Name: "Jhon", Age:28},
Children: [{..},{..}]
}
You can use Json To Java Class.
// import com.fasterxml.jackson.databind.ObjectMapper; // version 2.11.1
// import com.fasterxml.jackson.annotation.JsonProperty; // version 2.11.1
/* ObjectMapper om = new ObjectMapper();
Payload payload = om.readValue(myJsonString), Payload.class); */
public class Payload {
#JsonProperty("Name")
public String name;
#JsonProperty("Age")
public int age;
#JsonProperty("Children")
public List<Children> children;
}
To have name and age on top level in the jsonc-ode you might want to try putting the attributes at top level of your Payload class:
class Payload{
String name;
int age;
Children x[];
}
Please let me know if this is helpful.
Related
With jackson there is a way to ignore some fields using #JsonIgnore. Is there a way to do the opposite, and only show fields with are annotated? I'm working with an external class with a lot of fields and I only want to select a small subset of them. I'm getting tons of recursion problems (using some type of ORM) where object A -> B -> A -> B -> A .... which are not even necessary to export.
You can configure the object mapper to ignore absolutely everything unless specified by JsonProperty,
public class JacksonConfig {
public static ObjectMapper getObjectMapper(){
//The marshaller
ObjectMapper marshaller = new ObjectMapper();
//Make it ignore all fields unless we specify them
marshaller.setVisibility(
new VisibilityChecker.Std(
JsonAutoDetect.Visibility.NONE,
JsonAutoDetect.Visibility.NONE,
JsonAutoDetect.Visibility.NONE,
JsonAutoDetect.Visibility.NONE,
JsonAutoDetect.Visibility.NONE
)
);
//Allow empty objects
marshaller.configure( SerializationFeature.FAIL_ON_EMPTY_BEANS, false );
return marshaller;
}
}
public class MyObject {
private int id;
#JsonProperty
private String name;
private Date date;
//Getters Setters omitted
in this case only name would be serialized.
Sample repo, https://github.com/DarrenForsythe/jackson-ignore-everything
Yes definitely you can; Create a class with only the feilds you need and add the below property in the object mapper and rest is done.
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES to false
You can use #JsonIgnoreProperties(ignoreUnknown=true) on the pojo class so only the fields which are available in the pojo class will be mapped and resf will be left out.
For example
Json data
{
"name":"Abhishek",
"age":30,
"city":"Banglore",
"state":"Karnatak"
}
pojo class
#JsonIgnoreProperties(ignoreUnknown=true)
Class Person{
private int id;
private String name;
private String city;
}
Here state in not present in the Person class so that field won't be mapped
I am using Jackson Mixin to deserialize mongo object and the Mixin looks as below.
public interface MyMixin {
/**
* Mixin to set key value for pojo.
* #param key key
* #param value value
*/
#JsonAnySetter
void put(String key, Object value);
}
The mixin works really well for all fields including list except for the id field.
The pojo looks as below.
public class MyPojo {
#JsonProperty("_id")
#javax.persistence.Id
private String id;
private String name;
}
The exception
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of java.lang.String out of START_OBJECT token
at [Source: (String)"{"_id": {"$oid": "5e049cb30eb7811fec0c7029"}
I understand that its failing to deserialize string from a nested json.
One way through which I solved the problem is via writing custom mapper
public static MyPojo map(final Document document) {
final MyPojo pojo = new MyPojo();
pojo.setUd(document.getObjectId("_id").toHexString());
// set other fields
return pojo;
But this requires change is mapper whenever there is a change in pojo, adding/removing fields.
The Mixin works without any change, How shall I update my Mixin to handle objectId as well?
I am not sure if you can have a mixin to handle this kind of case in a generic way. I propose a solution that has not much to do with mixin but gives one generic way to deserialize such fields. First create a class to represent the json id:
#Getter #Setter
public class OidId {
#JsonProperty("$oid")
private String oid;
}
Then an abstract class to have the mapping stuff:
public abstract class HasOidId {
// moved from MyPojo
#JsonProperty("_id")
#javax.persistence.Id
private String id;
#JsonSetter("_id") // this is the trigger for mapping "_id" stufff
public void setId(OidId oidId) {
this.id = oidId.getOid();
}
}
Then let MyPojo extend above:
#Getter #Setter
public class MyPojo extends HasOidId {
private String name;
}
Is there any way to serialize a class into json but only with fields I want to use in particular case without need of creating multiple variations of class?
Let's take an example:
class User{
#JsonField
private String name;
#JsonField
private String surname;
#JsonField
private String hashedCode;
#JsonField
private String city;
#JsonField
private String anotherDummyString;
}
Now in one of my methods I would like to have a mapping to json Object which only contains name, city and anotherDummyString.
In Second method I want to have surname and city. In third method ... .
Is there any pleasant and neat way to achive this?
I was wondering if I can "hide" these fields which I don't need.
Are you looking for something like this? (Using javax.json)
JsonObject getJson1() {
return Json.createObjectBuilder().add("name", this.name).add("city", this.city).build();
}
JsonObject getJson2() {
return Json.createObjectBuilder().add("surname", this.surname).add("city", this.city).build();
}
Just .add what you need in each function call.
I hope you are looking for a kind of filter for your fields in Class
This can be achieved using Jackson #JsonFilter
package com.concretepage;
import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.annotation.JsonProperty;
#JsonFilter("student")
public class Student
{
#JsonProperty("name")
private String name;
#JsonProperty("surname")
private String surname;
#JsonProperty("hashedCode")
private String hashedCode;
#JsonProperty("city")
private String city;
#JsonProperty("anotherDummyString")
private String anotherDummyString;
}
Create a simple filter for you above class
SimpleFilterProvider filterProvider = new SimpleFilterProvider();
filterProvider.addFilter("student",
SimpleBeanPropertyFilter.serializeAllExcept("name", "city","anotherDummyString"));
Set it to a object mapper
ObjectMapper mapper = new ObjectMapper();
mapper.setFilterProvider(filterProvider);
To get the json message
//Pass the student object
String jsonData = mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(student);
You must able to have you 2 variance of class by creating one more sample filter like above
I'm kind of new in jackson subject and I did not find any answer which would help me resolve the problem.
For a sec let's assume that I have this class:
public class Airport {
private String name;
private String code;
...
}
My json looks like this:
"XXX": {
"name": "SomeName",
}
I would like to force Jackson to put XXX (root of tree) into code property from the class. Standard way I use to create objects from JSON is using treeToValue:
ObjectMapper mapper = new ObjectMapper();
String airports = "above Json";
JsonNode airportsTree = mapper.readTree(airports.toString());
Airport airport = mapper.treeToValue(airportsTree, Airport.class);
However when I enable DeserializationFeature.UNWRAP_ROOT_VALUE I'm getting
JsonMappingException: Root name 'XXX' does not match expected ('JsonNode') for type [simple type, class com.fasterxml.jackson.databind.JsonNode]
You need put root name hint for jackson
#JsonRootName(value = "XXX")
public class Airport {
private String name;
private String code;
...
}
When you enable DeserializationFeature.UNWRAP_ROOT_VALUE it must works
I am doing POJO serialization / deserialization using Jackson.
Here is a POJO exemple :
public class Pojo {
public String productId;
public String name;
}
I have to read the field productId in this JSON :
{"productId":"1","name":"exemple"}
But also in :
{"_id":"1","name":"exemple"}
To make it short, I would like to use the same object to read the field in a JSON file found somewhere and to save the object as this in MongoDB, using productId as the primary key, which has to be named _id.
Since I am using Jackson (fasterxml) both to read from the file and to write to the database, I can not find a way to do so, except by creating a new class with the same fields (or inheritance) and fill them one by one. Basically, I would like to find a way to put 2 #JsonProperty annotations on productId.
Works with both strings:
public class Pojo {
#JsonProperty("_id")
public String productId;
public String name;
#JsonProperty("productId")
public void setProductId(String id) {
productId = id;
}
}