Can get field from inner json object with jackson? - java

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

Related

Ignore enclosing braces with JSON parser while serializing object in Java

I have the following classes:
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonInclude(JsonInclude.Include.NON_NULL)
public class User {
private String id;
private List<Reference> references;
.....
}
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Reference {
#JacksonXmlProperty(isAttribute = true)
private String ref;
public Reference(final String ref) {
this.ref = ref;
}
public Reference() { }
public String getRef() {
return ref;
}
}
When serializing to XML the format is as expected, but when I try to serialize to JSON I get the following
"users" : [
{
"references" : [
{
"ref": "referenceID"
}
]
}
]
And I need it to be:
"users" : [
{
"references" : [
"referenceID"
]
}
]
the braces enclosing the reference list I need it to be ignored without the attribute name
You can annotate the ref field in your Reference class with the JsonValue annotation that indicates that the value of annotated accessor is to be used as the single value to serialize for the instance:
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Reference {
#JacksonXmlProperty(isAttribute = true)
#JsonValue //<-- the new annotation
private String ref;
public Reference(final String ref) {
this.ref = ref;
}
public Reference() { }
public String getRef() {
return ref;
}
}
User user = new User();
user.setReferences(List.of(new Reference("referenceID")));
//it prints {"references":["referenceID"]}
System.out.println(jsonMapper.writeValueAsString(user));
Edit: it seems that the JsonValue annotation invalidates the serialization of the class as expected by the OP; to solve this problem one way is the use of a mixin class for the Reference class and putting inside the JsonValue annotation, the original Reference class will be untouched:
#Data
public class MixInReference {
#JsonValue
private String ref;
}
ObjectMapper jsonMapper = new ObjectMapper();
//Reference class is still the original class
jsonMapper.addMixIn(Reference.class, MixInReference.class);
////it prints {"references":["referenceID"]}
System.out.println(jsonMapper.writeValueAsString(user));

Multiple DTOs manual initialize

in Microservice, we post multiple dtos data as string json.
Controller:
#RequestMapping(value="/json",method = RequestMethod.POST)
public String getjson(#RequestBody String json) {
///Service process
}
Post Json:
{
"dtos":{
"Dto1":{
"name":"Dto1 Name Field",
"filter":[
{"key":"f1","value":1},
{"key":"f2","value":10}
]
},
"Dto2":{
"city":"Newyork",
"filter":[
{"key":"f1","value":1},
{"key":"f2","value":10},
{"key":"f3","value":10}
]
}
},
"page":1
}
DTO:
public class Dto1{
private String name;
}
public class Dto2{
private String city;
}
Dto1 and Dto2 is java DTO object name.
how to convert string json to java objects?
You can create a new DTO that contains all attrs and receive in request:
public class Filter{
private String key;
private int value;
}
public class Dto1{
private String name;
private List<Filter> filter;
}
public class Dto2{
private String city;
private List<Filter> filter;
}
public class Dtos{
public Dto1 dto1;
public Dto2 dto2;
}
public class DtoToReceiveInRequest{
private Dtos dtos;
private int page;
}
Controller
#PostMapping
public String getjson(#RequestBody DtoToReceiveInRequest json) {
///Service process
}
You can use the ObjectMapper from the jackson library, like below.
String json = "";
ObjectMapper objectMapper = new ObjectMapper();
Dto1 dto = objectMapper.readValue(json, Dto1.class);
But in your particular example, you don't have to have two DTO classes. You can encapsulate values in one DTO and have the list of different instances of that DTO in a json format.
NB. The json string should be a representation of the preferred class you want to retrieve, eg Dto1.java.

Change one field from string to json object in jackson

I have a class where employeeDetails is being read from a data store as json string.
public class Employee {
private String name;
#JsonProperty("employeeDetails")
#JsonSerialize(???)
private String employeeDetailsBlob;
// getters and setters
}
Now I want to return employeeDetails(dynamic type) as an object in my response. I have changed the name using #JsonProperty and all the examples I have is for using #JsonSerialize(using = Employee.class).
So my response should look like this
{name: "foo", employeeDetails: { age: 21 }}
What I am getting is
{name: "foo", employeeDetails: "{ age: 21 }"}
I can add #JsonSerialize to my class but then I have to handle all the fields myself and do something like this in the overridden method.
jgen.writeFieldName("employeeDetails");
SerializedString serializedString = new SerializedString(empl.getEmployeeDetailsBlob());
jgen.writeRawValue(serializedString);
Is there a way I can do it using annotations and that too only on the field I want to change from json string to json object.
Adding #JsonRawValue did the trick.
public class Employee {
private String name;
#JsonProperty("employeeDetails")
#JsonRawValue
private String employeeDetailsBlob;
// getters and setters
}

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;

Can't serialize with Jackson Json class fields if it extends ArrayList

I'm using Jackson Json. I can't serialize class fields if class extends ArrayList.
Class:
public class DataElement {
private Date date;
private int val1;
private int val2;
// constructor, getters, setters
}
public class DataArray extends ArrayList<DataElement> {
private String info;
private int num;
// constructor, getters, setters
}
Serialization:
ObjectMapper jsonMapper = new ObjectMapper();
jsonMapper.writeValue(new File("path"), dataArray);
Result file contains DataElements only:
[ {
"date" : 1446405540000,
"val1" : 10296,
"val2" : 30365
}, {
"date" : 1446405600000,
"val1" : 40164,
"val2" : 20222
} ]
'num' and 'info' are not saved into file.
How to save full class including its fields?
Jackson will serialize your POJOs according to the JsonFormat.Shape. For an ArrayList object that is ARRAY. You can change the shape to OBJECT with an annotation.
#JsonFormat(shape = JsonFormat.Shape.OBJECT)
public class DataArray extends ArrayList<DataElement> {
Make sure DataArray has a getter that returns an ArrayList for e.g.
public ArrayList<DataElement> getContents() {
return new ArrayList<>(this);
}
When I tried the above code I saw this field at the resulting JSON
"empty":false
You can use #JsonIgnore to prevent that from appearing

Categories