Jackson Json to POJO mapping - java

i am i little lost in creating a mapping with jackson. My Json has the following structure
{
"d": {
"__metadata": {
"uri": "https://apisalesdemo8.successfactors.com:443/odata/v2/JobApplication(1463L)",
"type": "SFOData.JobApplication"
},
"lastName": "K",
"address": "123 Main Street",
"cellPhone": "12345",
"firstName": "Katrin",
"city": "Anytown",
"country": "United States",
"custappattachment": {
"results": [
{
"__metadata": {
"uri": "https://apisalesdemo8.successfactors.com:443/odata/v2/Attachment(1188L)",
"type": "SFOData.Attachment"
},
"fileExtension": "jpeg",
"fileName": "hp-hero-img.jpeg",
"fileContent": "/9j/4AA"
},
{
"__metadata": {
"uri": "https://apisalesdemo8.successfactors.com:443/odata/v2/Attachment(1189L)",
"type": "SFOData.Attachment"
},
"fileExtension": "jpeg",
"fileName": "hp-content-bkgd-img.jpeg",
"fileContent": "/9j/4AAQSk"
}]}}}
I do find a lot of tutorials handling arrays, but i fail already with the very first token "d".
and all the "__metadata" token are not needed at all.
I created a pojo containing attributes like lastName etc. and a collection attachments.
But my code always fails at token "d" or "__metadata"
public class ResponseDataObject {
private String lastName;
private String address;
private String cellPhone;
private String firstName;
private String city;
private String country;
private List<Attachment> attachments = new ArrayList<>();
.....getters and setters
and the jackson reader
ObjectReader objectReader =
mapper.readerFor(ResponseDataObject.class);
ResponseDataObject dataObject = objectReader.readValue(file);
Any hints would be appreciated.
Regards
Mathias

You can use #JsonIgnoreProperties annotation to ignore the properties that don't match any of the members defined in class, e.g.:
#JsonIgnoreProperties(ignoreUnknown = true)
public class ResponseDataObject {
This will make sure all the matching properties are mapped and other properties are ignored.

You need to ignore properties, not present in POJO. Set following property in DeserializationFeature for ObjectMapper:
// for version 1.x
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// for newer versions
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
Deserialization code:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
ResponseDataObject dataObject = mapper.readValue(file, ResponseDataObject.class);
and add this annotation to ResponseDataObject class:
#JsonRootName(value = "d")
class ResponseDataObject {

Related

Jackson deserializing json choosen fields

there is possibility to deserialize Json only choosen fields?
Eg:
{
"Version": 1,
"Key": "353301_PC",
"Type": "PostalCode",
"Rank": 500,
"LocalizedName": "Kleosin",
"EnglishName": "Kleosin",
"PrimaryPostalCode": "16-001",
"Region": {
"ID": "EUR",
"LocalizedName": "Europe",
"EnglishName": "Europe"
}
And i want only LocalizedName and EnglishName. Tried with objectMapper but getting errors.
Add JsonIgnoreProperties annotation to your data class
#JsonIgnoreProperties(ignoreUnknown = true)
public class YourClass {
private String LocalizedName;
private String EnglishName;
...
}
you can add #JsonIgnore to the fields inside the Region class

How to ignore field depending on method?

How to ignore filed field depending on method?
I have a question about Spring Jackson annotations.
I have a model class. Code:
public class Tenant{
#JsonIgnore
private String id;
#JsonProperty("id")
#JsonDeserialize(using = StringValueDeserializer.class)
private String idSIMC;
#JsonProperty("name")
private String displayName;
#JsonProperty("description")
private String description;
#JsonProperty("default")
private boolean def;
#JsonProperty("geoLoc")
#JsonDeserialize(using = GeoLocationIdNameDeserializer.class)
private GeoLocation geoLoc;
#JsonProperty("asnId")
private String asnId;
#JsonProperty("devices")
#JsonDeserialize(using = StringArrayIdDeserializer.class)
private List<String> tempDevice = Collections.synchronizedList(new ArrayList<>());
#JsonIgnore
#JsonProperty("devices") // <-- I need to add this
private List<Device> devices = Collections.synchronizedList(new ArrayList());
//getters and setters...
}
Now my question. I have method#1 that instance above class and write in tempDevice IDs of devices. method#2 get all devices from servers and filter them by tempDevice (I need to do it) can I annotate ( or something else ) my fields to be ignored as Json Objects depending on method is called?
method#1
public List<Tenant> getTenantsFromServer() {
SSLVerification.disableSslVerification();
ArrayList<Tenant> tenants = new ArrayList<>(0);
String[] ids = getTenantIds();
for(int i=0; i<ids.length; i++){
ResponseEntity<ReturnUnique<Tenant>> result = getRestTemplate().exchange(getUrl() + SIEMCommands.ZONE_GET_ZONE + "?id=" + ids[i],
HttpMethod.GET, new HttpEntity(getHeader()), new ParameterizedTypeReference<ReturnUnique<Tenant>>(){});
Tenant newTenant = result.getBody().getValue();
newTenant.setParentNode(this);
newTenant.generateId();
tenants.add(newTenant);
}
return tenants;
}
In this method i have a key "devices" in that is stored id. In method#2 another json that also have "devices" key but with another dates.(name,ip, etc.) And when I execute this method I should to store all in devices list.
JSON used in first method#1
{"return": {
"asnId": 0,
"default": false,
"description": "",
"devices": [
{"id": 144121785900597248},
{"id": 144121785917374464},
{"id": 144121785934151680}
],
"geoLoc": {
"id": {"value": 0},
"name": ""
},
"id": {"value": 1},
"name": "HA_Zone"
}}
devices values are written in tempDevice;
method#2 use this JSON
"devices": [{
"CRuleRight": true,
"FTestRight": true,
"adRight": true,
"addDeleteRight": false,
"children": [],
"clientCount": 0,
"clientStatus": "0",
"clientVipsInSync": false,
"deviceActionRight": true,
"deviceDisabled": false,
"elmFile": false,
"elmHasSAN": false,
"eventRight": true,
"hostname": "",
"ipAddress": "172.28.60.17",
"ipsID": "144121785950928896",
"ipsRight": true,
"name": "ASA Admin CTX Site 2",
"parent": false,
"polRight": true,
"protocol": "gsyslog",
"reportRight": true,
"status": "6",
"statusAck": "0",
"tpcCollector": "syslog",
"tpcType": "278",
"type": "VIPS",
"viewRight": true,
"vipsEnabled": true,
"vipsID": "49",
"vipsInSync": false
},
{
"CRuleRight": true,
"FTestRight": true,
"adRight": true,
"addDeleteRight": false,
"children": [],
"clientCount": 0,
"clientStatus": "0",
"clientVipsInSync": false,
"deviceActionRight": true,
"deviceDisabled": false,
"elmFile": false,
"elmHasSAN": false,
"eventRight": true,
"hostname": "",
"ipAddress": "172.28.13.10",
"ipsID": "144121785179176960",
"ipsRight": true,
"name": "ASA-VPN-DC1",
"parent": false,
"polRight": true,
"protocol": "gsyslog",
"reportRight": true,
"status": "0",
"statusAck": "0",
"tpcCollector": "syslog",
"tpcType": "278",
"type": "VIPS",
"viewRight": true,
"vipsEnabled": true,
"vipsID": "3",
"vipsInSync": false
}
}]
this dates i have to write in devices
If I understand correctly, you are looking for a way to deserialize 2 different json datatype having same property name into a object in different situation. If that is the case, the suggestion of using JacksonMixInAnnotations from #Thomas should work. JacksonMixInAnnotations can provide a kind of way to add annotation from another class (called mix-in class) to the target class during run time.
In your case, you can left tempDevice and devices without Jackson annotation like follows:
public class Tenant {
private List<String> tempDevice;
private List<Device> devices;
}
and declare 2 mix-in classes:
abstract class TempDeviceMixIn {
#JsonProperty("devices")
private List<String> tempDevice;
}
abstract class DeviceMixIn {
#JsonProperty("devices")
private List<Device> devices;
}
When you need to deserialize a json string with a string property of devices, you can add mix-in class annotation likes:
ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(Tenant.class, TempDeviceMixIn.class);
Tenant tenant = mapper.readValue(json, Tenant.class);
Deserialize a json string with a object property of devices is similar.
As you are using RestTemplate, you will need a MappingJacksonHttpMessageConverter with your ObjectMapper.

How to add root node in JSON

I need to include the top node in my JSON response. My JSON response in REST web service:
[
{
"address": "delhi",
"fristname": "xxxx",
"id": 1,
"lastname": "xxxx",
"phone": "0000000"
},
{
"address": "ssss",
"fristname": "yyyy",
"id": 2,
"lastname": "yyyyy",
"phone": "0000000"
},
{
"address": "wwww",
"fristname": "aaaa",
"id": 3,
"lastname": "aaaaa",
"phone": "0000000"
}
]
I want JSON response like this:
"employee": [
{
"address": "delhi",
"fristname": "xxxx",
"id": 1,
"lastname": "xxxx",
"phone": "0000000"
},
{
"address": "ssss",
"fristname": "yyyy",
"id": 2,
"lastname": "yyyyy",
"phone": "0000000"
},
{
"address": "wwww",
"fristname": "aaaa",
"id": 3,
"lastname": "aaaaa",
"phone": "0000000"
}
]
Please tell me how to add root node JSON. Thanks in advance.
You can do it like this in Java. Create a new JSON object and put your array in it.
JSONObject myobj = new JSONObject();
myobj.put("employees", <your_json_array>);
You could use Jackson annotation JsonRootName:
Annotation similar to XmlRootElement, used to indicate name to use for
root-level wrapping, if wrapping is enabled. Annotation itself does
not indicate that wrapping should be used; but if it is, name used for
serialization should be name specified here, and deserializer will
expect the name as well.
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
And annotate your class as follows:
#JsonRootName(value = "employee")
public static class Employee {
private String address;
private String firstName;
// more... with getters and setters
}
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class Employee
{
public string address { get; set; }
public int phone { get; set; }
}
public partial class Samplepage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
List<Employee> eList = new List<Employee>();
Employee employee = new Employee();
employee.address = "Minal";
employee.phone = 24;
eList.Add(employee);
employee = new Employee();
employee.address = "Santosh";
employee.phone = 24;
eList.Add(employee);
string ans = JsonConvert.SerializeObject(eList, Formatting.Indented);
JArray a = JArray.Parse(ans);
JObject UpdateAccProfile = new JObject(
new JProperty("employee", a)
);
}
}

How to represent sub-documents in JSON array as Java Collection using Jackson?

I would appreciate any help to know the best way to deserialize the following JSON response which we receive from Salesforce into a Java object using Jackson Annotations.
"records": [
{
"attributes": {
"type": "Lead",
"url": "/services/data/v30.0/sobjects/Lead/00Qi000000Jr44XEAR"
},
"Id": "00Qi000000Jr44XEAR",
"Name": "Kristen Akin",
"Address": {
"city": null,
"country": "USA",
"state": "CA",
"stateCode": null,
"street": null
},
"Phone": "(434) 369-3100",
},
{
"attributes": {
"type": "Lead",
"url": "/services/data/v30.0/sobjects/Lead/00Qi000000Jugv2EAB"
},
"Id": "00Qi000000Jugv2EAB",
"Name": "Sarah Jones",
"Address": {
"city": null,
"country": null,
"state": "CA",
"stateCode": null,
"street": null
},
"Phone": "(408) 338-6066",
}
]}
The above JSON response is an array which contains 2 elements. I would like to represent this JSON structure as a Java Collection using Jackson, something like:
#JsonProperty("records")
ArrayList<LinkedHashMap<?, ?>> recordList
The above object representation deserializes the JSON response and represent as a Key-Value pair in HashMap but issue is representing "attributes" and "Address" subdocuments. In the above HashMap their value is being represented as the respective JSON subdocument whereas I would prefer to have Attributes subdocument gets mapped to an Attribute object and similarly Address subdocument mapped to an Address object in the HashMap, something like:
Key Value
attributes <Attributes> object
Id 00Qi000000Jr44XEAR
.....
Address <Address> object
Phone (434) 369-3100
After doing some Google search, I figured I might have to use #JsonTypeInfo and #JsonSubTypes attributes as mentioned in this link.
However, I could not figure how to use these annotations in this specific scenario. Appreciate any help on this.
If the structure of your JSON input is completely dynamic, you can read it as JsonNode or even as Map. Refer to this link for more info.
If you want to map your JSON to java classes but you don't know all the attributes in compile type, you can leverage the #JsonAnyGetter/#JsonAnySetter annotations. Here is an example based on your JSON that stores the unknown attributes for the Address class in the internal map.
public class JacksonMapping {
public static final String JSON = "...";
public static class Attributes {
public String type;
public URI url;
}
public static class Address {
public String city;
public String country;
public String state;
public Integer stateCode;
public String street;
private final Map<String, Object> otherAttributes = new HashMap<>();
#JsonAnySetter
public void setProperty(String name, Object value) {
otherAttributes.put(name, value);
}
#JsonAnyGetter
public Map<String, Object> getOtherAttributes() {
return otherAttributes;
}
}
public static class Record {
#JsonProperty("Id")
public String id;
#JsonProperty("Name")
public String name;
public Attributes attributes;
#JsonProperty("Address")
public Address address;
#JsonProperty("Phone")
public String phone;
}
public static class RecordList {
public List<Record> records;
}
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
RecordList recordList = mapper.readValue(JSON, RecordList.class);
System.out.println(mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(recordList));
}
}
I can also try to generate java objects from your JSON with a help from a tool. For example this one: http://www.jsonschema2pojo.org

How to map JSON data into any Object in JAVA?

I would like to map from JSON-Response into my Java Object using Jersey. I have this such Json response:
{
"act": "add",
"col": "student",
"data": [
{
"firstName": "alex",
"lastName": "homer",
"age": "18",
"roomNo": "1301"
},
{
"firstName": "alex",
"lastName": "homer",
"age": "18",
"roomNo": "1301"
}
]
}
And this is my bean that I'd like to map the Json-response into:
#XmlRootElement(name = "request")
#XmlAccessorType(XmlAccessType.FIELD)
public class RequestAction implements RequestOperations {
#XmlElement(required = true, name = "act")
private String action;
#XmlElement(required = true, name = "col")
private String collectionName;
#XmlElement(required = false, name = "oid")
private String objectId;
#XmlElement(name = "data")
private List<Object> data;
public RequestAction() {
}
//getters setters
}
So, my problem is how to map data under "data": {[....]}?
Because it also can be identified with any Object.
For this example, the object is Customer. How about if object is Student, Animal, or anything else? If possible, I dont need create that object (I means Customer, and others).
Do you have any idea or suggestion?
Consider use of Gson library: https://code.google.com/p/google-gson/
I didn't have a problem with lists there.
if your bean property name are the same as your JSON's, you can use json-lib.
For maven project, just put
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
into the pom.xml.
JSONObject jsonObject = (JSONObject) JSONSerializer.toJSON(YOUR JSON STRING);
RequestAction re = (RequestAction) JSONObject.toBean(jsonObject,RequestAction.class);

Categories

Resources