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);
Related
I'm receiving a response from one third party service which looks like this:
{
"field1": "string",
"field2": "string",
"objectList": [
{
"object1": {
"field11": "string",
"field12": "string",
"field13": "string",
"field14": "string",
},
"object2": {
"field21": "string",
"field22": "string",
"field23": "string",
},
"object3": {
"field31": "string",
"field32": "string",
"field33": "string",
"field34": "string",
"field35": "string",
}
}
]
}
object1, object2 and object3 are not the same type, and I just want to get the object2 from the response.
I have tried this approach:
ResponseEntity<ResponseClass> response = restTemplate.exchange( uri, HttpMethod.POST, entity, ResponseClass.class );
Where ResponseClass looks like this:
#JsonIgnoreProperties(ignoreUnknown = true)
#Data
public class ResponseClass implements Serializable {
private static final long serialVersionUID = -4355652702566088304L;
#JsonProperty("field1")
private String field1;
#JsonProperty("field2")
private String field2;
#JsonProperty("objectList")
private List objectList;
And I'm getting the full objectList, so I can extract it as key value pairs like objectList.get(0).get("object2") or something like that. But I'm unsure if there is a better solution.
Can anyone please provide some guidance on how to improve this or how to get just the object I want?
There are two ways to look at it.
Extensibility and pure object-oriented way:
You need to map the whole response object properly at your side rather than having an ambiguous List. An array should always have objects of same type. In your example too basically you have a list of wrapper object which hold object1, object2, and object3.
So, basically you should do something like this :
#JsonIgnoreProperties(ignoreUnknown = true)
#Data
public class ResponseClass implements Serializable {
private static final long serialVersionUID = -4355652702566088304L;
#JsonProperty("field1")
private String field1;
#JsonProperty("field2")
private String field2;
#JsonProperty("objectList")
private List<IntendedObject> objectList;
}
#JsonIgnoreProperties(ignoreUnknown = true)
#Data
public class IntendedObject {
#JsonProperty("object2")
private Object2 object2;
}
The other way would be to have the response in a JsonNode and then do getProperty() over it if you don't want to map it over to a custom object.
objectList[0].object2
0 gives you the first item in the list
Then object2 accesses the value of the dictionary
I need to deserialize JSON to java class.
I have JSON like the following:
{
"data": {
"text": "John"
},
"fields":[
{
"id": "testId",
"name": "fieldName",
"options": {
"color": "#000000",
"required": true
}
},
{
"id": "testId",
"name": "fieldName1",
"options": {
"color": "#000000",
"required": false
}
}
]
}
and I need to deserialize this JSON (only "fields" section) to java class like the following:
public class Field {
public final String id;
public final String name;
public final String color;
public final boolean required;
}
and I need to get something like the following:
// The key is the id from field object (it can be the same in the multiple objects.)
Map<String, List<Field>> fields = objectMapper.readValue(json, Map<String, List<Field>>);
How can I do it using Jackson?
As long as jackson doesn't support #JsonWrapped, you have to use the following work around.
First you need to create a custom class which contains the fields:
public class Fields {
public List<Field> fields;
}
Depending on your ObjectMapper configuration you have to add #JsonIgnoreProperties(ignoreUnknown = true) to the Fields class, to ignore any other properties.
Next is that you have to define the nested Options class which is solely used temporarily:
public class Options {
public String color;
public boolean required;
}
And at last add this constructor to your Field class:
#JsonCreator
public Field(#JsonProperty("id") String id, #JsonProperty("name") String name, #JsonProperty("options") Options options){
this.id = id;
this.name = name;
this.color = options.color;
this.required = options.required;
}
The #JsonCreator annotation indicates to jackson that this constructor needs to be used for the deserialization. Also the #JsonProperty annotations are required as arguments to constructors and methods are not preserved in the bytecode
Then you can deserialize your json just like this:
List<Field> fields = objectMapper.readValue(json, Fields.class).fields;
I am using spring restTemplate to map a response to a POJO.
The response of the rest api is like this:
"attributes": {
"name": {
"type": "String",
"value": ["John Doe"]
},
"permanentResidence": {
"type": "Boolean",
"value": [true]
},
"assignments": {
"type": "Grid",
"value": [{
"id": "AIS002",
"startDate": "12012016",
"endDate": "23112016"
},{
"id": "AIS097",
"startDate": "12042017",
"endDate": "23092017"
}]
}
}
in the parent class, I have:
public class Users {
private Map<String, Attribute> attributes;
}
If all the values of were String type, then I could have done like:
public class Attribute {
private String type;
private String[] value;
}
But the values are of different types. So I thought of doing the following:
public class Attribute {
private String type;
private Object[] value;
}
The above should work, but at every step I have to find out what is the type of Object.
So, my question is can I have something like this:
public class Attribute {
#JsonProperty("type")
private String type;
#JsonProperty("value")
private String[] stringValues;
#JsonProperty("value")
private Boolean[] booleanValues;
#JsonProperty("value")
private Assignments[] assignmentValues; // for Grid type
}
But it is not working and throwing errors: Conflicting setter definitions for property "value"
What is the recommended way of handling this scenario?
I would recommend Jackson facilities for handling polymorphism here:
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
#JsonSubTypes({
#JsonSubTypes.Type(value = BooleanAttribute.class, name = "Boolean"),
#JsonSubTypes.Type(value = StringAttribute.class, name = "String")
})
class Attribute {
private String type;
}
class BooleanAttribute extends Attribute {
private Boolean[] value;
}
class StringAttribute extends Attribute {
private String[] value;
}
JsonTypeInfo tells Jackson that this is a base class and the type will be determined by a JSON field named "type"
JsonSubTypes maps subtypes of Attribute to values of "type" in JSON.
If you add an appropriate subtype for Assignments and getters/setters Jackson will be able to parse your JSON.
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 {
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