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
Related
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 have a Json as shown below:-
{
"componentModelData": {
"modelNumber": "ABC",
"modelName": "",
"modelDescription": "",
"modelVendor": null,
"componentName": "HELO"
},
"revisionData": {
"revisionName": "rev12",
"revisionComment": "Comment",
"modifiedBy": "2323553"
},
"configData": [{"nodes":2085,"FxPOS-SX":16.5051,"FxPOS-SY":11.0479,"FxPOS-SZ":115.3421,"FxPOS-SXY":-13.8094,"FxPOS-SYZ":36.0105
},{"nodes":2085,"FxPOS-SX":16.5051,"FxPOS-SY":11.0479,"FxPOS-SZ":115.3421,"FxPOS-SXY":-13.8094,"FxPOS-SYZ":36.0105}]
}
DataMapping.java
#Getter
#Setter
#JsonSerialize
#NoArgsConstructor
#AllArgsConstructor
public class DataMapping implements Serializable {
/**
*
*/
private static final long serialVersionUID = -2635323042843403966L;
#JsonProperty("componentModelData")
#Valid
public ComponentModelDTO componentModelDTO;
#JsonProperty("revisionData")
#Valid
public RevisionDTO revisionDTO;
#JsonProperty("configData")
private List<Object> configData;
}
I want to convert the configData list to List<HashMap<String,Double>> list where String is the keys like 'nodes,FxPOS-SX,FxPOS-SY' and value is their respective values.
Can anyone please help me how can i achieve this?
Just replace List<Object> with List<Map<String,Double>>. Jackson will do the hard work for you:
#JsonProperty("configData")
private List<Map<String, Double>> configData;
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'm trying to parse JSON like the following into object using Jackson on Android (Note: I'm not in control of the JSON format - the format comes from Yammer)
"references": [
{
"type": "user",
"id": 12345678,
"name": "Wex"
},
{
"type": "message",
"id": 12345679,
"body":
{
"plain":"A short message"
}
},
{
"type": "thread",
"id": 12345670,
"thread_starter_id": 428181699
}
]
The problem is that each entry in references is a different type of object with different properties. As a start I've got:
public static class Reference
{
public String type;
public String id;
}
I'd rather avoid putting all potential properties in one object like:
public static class Reference
{
public static class Body
{
public String plain;
}
public String type;
public String id;
public String name;
public Body body;
public String thread_starter_id;
}
And want to use separate classes that are created dependant on the type value like:
public static class ReferenceUser extends Reference
{
public String name;
}
public static class ReferenceMessage extends Reference
{
public static class Body
{
public String plain;
}
public Body body;
}
public static class ReferenceThread extends Reference
{
public String thread_starter_id;
}
So... what's the best way of getting Jackson to parse the JSON like that?
I'm currently parsing it quite simply like this:
ObjectMapper mapper = new ObjectMapper();
Reference[] references = mapper.readValue(json, Reference[].class);
you can do something like this with Jackson:
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
#JsonSubTypes({
#JsonSubTypes.Type(name = "user", value = ReferenceUser.class),
#JsonSubTypes.Type(name = "message", value = ReferenceMessage.class),
#JsonSubTypes.Type(name = "thread", value = ReferenceThread.class)
})
public class Reference {
int id;
String name;
}
This way you will generate subclasses.
John
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);