Jackson : deserializing a map - java

I'm using Jackson to deserialize a json file from a HTTP Response:
ObjectMapper mapper = new ObjectMapper();
InputStream responseBody = response.getBody().in();
RawDataBody rawdataBody = mapper.readValue(responseBody, RawDataBody.class);
I also tries this but it doesn't work :
RawDataBody rawdataBody = mapper.readValue(responseBody.toString(), RawDataBody.class);
This is the error that I'm getting :
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of com.ubiant.hemis.accounts.TineaSeas.Model.RawDataBody out of START_ARRAY token at [Source: java.io.ByteArrayInputStream#19da0cd; line: 1, column: 1]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:575)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:569)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromArray(BeanDeserializerBase.java:1120)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:148)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:123)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2080)
at com.ubiant.hemis.accounts.TineaSeas.Test.main(Test.java:46)
The JSON File :`
[
{
"tag":"Volume_D1_10m",
"value":0.0,
"quality":1,
"site":1,
"supplier":2,
"zone":0,
"timestamp":1470297561000
},
{
"tag":"Tmoy_T4_10m",
"value":19.2,
"quality":1,
"site":1,
"supplier":2,
"zone":0,
"timestamp":1470297561000
}
]
This is my model :`
public class RawDataBody implements Serializable {
#JsonProperty("rawDatas")
#JsonDeserialize
private ArrayList<RawData> rawDatas = new ArrayList<RawData>();
public RawDataBody(){
}
public RawDataBody rawDatas(ArrayList<RawData> rawDatas) {
this.rawDatas = rawDatas;
return this;
}
#JsonProperty("rawDatas")
public ArrayList<RawData> getRawDatas() {
return rawDatas;
}
#JsonProperty("rawDatas")
public void setRawDatas(ArrayList<RawData> rawDatas) {
this.rawDatas = rawDatas;
}
public class RawData implements Serializable {
private String tag = null;
private Double value = null;
private Integer quality = null;
private Integer site = null;
private Integer supplier = null;
private Integer zone = null;
private BigDecimal timestamp = null;
#JsonProperty("tag")
public String getTag() {
return tag;
}
#JsonProperty("tag")
public void setTag(String tag) {
this.tag = tag;
}
#JsonProperty("value")
public Double getValue() {
return value;
}
#JsonProperty("value")
public void setValue(Double value) {
this.value = value;
}
#JsonProperty("quality")
public Integer getQuality() {
return quality;
}
#JsonProperty("quality")
public void setQuality(Integer quality) {
this.quality = quality;
}
#JsonProperty("site")
public Integer getSite() {
return site;
}
#JsonProperty("site")
public void setSite(Integer site) {
this.site = site;
}
#JsonProperty("supplier")
public Integer getSupplier() {
return supplier;
}
#JsonProperty("supplier")
public void setSupplier(Integer supplier) {
this.supplier = supplier;
}
#JsonProperty("zone")
public Integer getZone() {
return zone;
}
#JsonProperty("zone")
public void setZone(Integer zone) {
this.zone = zone;
}
#JsonProperty("timestamp")
public BigDecimal getTimestamp() {
return timestamp;
}
#JsonProperty("timestamp")
public void setTimestamp(BigDecimal timestamp) {
this.timestamp = timestamp;
}
}
Can anyone help me with this ?

There are two possible approaches:
Approach 1
Considering the existing JSON:
[
{
"tag": "Volume_D1_10m",
"value": 0,
"quality": 1,
"site": 1,
"supplier": 2,
"zone": 0,
"timestamp": 1470297561000
},
{
"tag": "Tmoy_T4_10m",
"value": 19.2,
"quality": 1,
"site": 1,
"supplier": 2,
"zone": 0,
"timestamp": 1470297561000
}
]
It can be serialized into a RawData array, as following:
String json = "[{\"tag\":\"Volume_D1_10m\",\"value\":0.0,\"quality\":1,\"site\":1,\"supplier\":2,\"zone\":0,\"timestamp\":1470297561000},{\"tag\":\"Tmoy_T4_10m\",\"value\":19.2,\"quality\":1,\"site\":1,\"supplier\":2,\"zone\":0,\"timestamp\":1470297561000}]";
ObjectMapper mapper = new ObjectMapper();
RawData[] rawDataArray = mapper.readValue(json, RawData[].class);
Approach 2
Modify your JSON to be like:
{
"rawDatas": [
{
"tag": "Volume_D1_10m",
"value": 0,
"quality": 1,
"site": 1,
"supplier": 2,
"zone": 0,
"timestamp": 1470297561000
},
{
"tag": "Tmoy_T4_10m",
"value": 19.2,
"quality": 1,
"site": 1,
"supplier": 2,
"zone": 0,
"timestamp": 1470297561000
}
]
}
And then serialize it into a RawDataBody:
String json = "{\"rawDatas\":[{\"tag\":\"Volume_D1_10m\",\"value\":0.0,\"quality\":1,\"site\":1,\"supplier\":2,\"zone\":0,\"timestamp\":1470297561000},{\"tag\":\"Tmoy_T4_10m\",\"value\":19.2,\"quality\":1,\"site\":1,\"supplier\":2,\"zone\":0,\"timestamp\":1470297561000}]}";
ObjectMapper mapper = new ObjectMapper();
RawDataBody rawDataBody = mapper.readValue(json, RawDataBody.class);

Related

Parsing JSON as Java Object is giving me some null values

I'm trying to convert a JSON object into a POJO class,
but some values are ending up with null values while
others are set to the value from the JSON.
The response is
{
"intention_id": 12936,
"intention_datetime": "2021-03-09T09:58:16-03:00",
"status": "created",
"cuit": "20-314559999-9",
"branch": "Avellaneda 13",
"checkout": "8",
"terminal_number": "87980012",
"intention_type": "payment",
"original_amount": 1200.0,
"currency": "ARS",
"payment_methods_data": [
{
"payment_method_id": 1,
"establishment_id": "29880765",
"trace_number": 1090,
"ticket_number": 131,
"installments": [
{
"quantity": 1,
"total_amount": 1200.0,
"amount_per_installment": 200.0,
"cft": 12.56,
"tna": 14.87
},
{
"bank_id": 28,
"quantity": 6,
"total_amount": 1200.0,
"amount_per_installment": 200.0,
"cft": 12.56,
"tna": 14.87
},
{
"quantity": 6,
"total_amount": 1400.0,
"amount_per_installment": 233.33,
"cft": 12.56,
"tna": 14.87
}
]
},
{
"payment_method_id": 15,
"establishment_id": "69880548",
"trace_number": 2034,
"ticket_number": 673,
"installments": [
{
"quantity": 1,
"total_amount": 1200.0,
"amount_per_installment": 200.0,
"cft": 12.56,
"tna": 14.87
},
{
"bank_id": 28,
"quantity": 6,
"total_amount": 1200.0,
"amount_per_installment": 200.0,
"cft": 12.56,
"tna": 14.87
},
{
"quantity": 6,
"total_amount": 1400.0,
"amount_per_installment": 233.33,
"cft": 12.56,
"tna": 14.87
}
]
}
],
"integrator_intention_id": "587cba61-ff27-46c6-ba8b-fd936665c35f",
"integrator": "alsea"
}
I'm ignoring the array elements,
so my Object Class is
public class ObjectResponseBimo {
public int intention_id;
public String intention_datetime;
public String status;
public String cuit;
public String branch;
public String checkout;
public String terminal_number;
public String intention_type;
public double original_amount;
public String currency;
public String integrator_intention_id;
public String integrator;
public int getIntention_id() {
return intention_id;
}
#JsonProperty("intention_id")
public void setIntention_id(int intention_id) {
this.intention_id = intention_id;
}
public String getIntention_datetime() {
return intention_datetime;
}
#JsonProperty("intention_datetime")
public void setIntention_datetime(String intention_datetime) {
this.intention_datetime = intention_datetime;
}
public String getStatus() {
return status;
}
#JsonProperty("status")
public void setStatus(String status) {
this.status = status;
}
public String getCuit() {
return cuit;
}
#JsonProperty("cuit")
public void setCuit(String cuit) {
this.cuit = cuit;
}
public String getBranch() {
return branch;
}
#JsonProperty("branch")
public void setBranch(String branch) {
this.branch = branch;
}
public String getCheckout() {
return checkout;
}
#JsonProperty("checkout")
public void setCheckout(String checkout) {
this.checkout = checkout;
}
public String getTerminal_number() {
return terminal_number;
}
#JsonProperty("terminal_number")
public void setTerminal_number(String terminal_number) {
this.terminal_number = terminal_number;
}
public String getIntention_type() {
return intention_type;
}
#JsonProperty("intention_type")
public void setIntention_type(String intention_type) {
this.intention_type = intention_type;
}
public double getOriginal_amount() {
return original_amount;
}
#JsonProperty("original_amount")
public void setOriginal_amount(double original_amount) {
this.original_amount = original_amount;
}
public String getCurrency() {
return currency;
}
#JsonProperty("currency")
public void setCurrency(String currency) {
this.currency = currency;
}
public String getIntegrator_intention_id() {
return integrator_intention_id;
}
#JsonProperty("integrator_intention_id")
public void setIntegrator_intention_id(String integrator_intention_id) {
this.integrator_intention_id = integrator_intention_id;
}
public String getIntegrator() {
return integrator;
}
#JsonProperty("integrator")
public void setIntegrator(String integrator) {
this.integrator = integrator;
}
#Override
public String toString() {
return "ObjectResponseBimo [intention_id=" + intention_id + ", intention_datetime=" + intention_datetime
+ ", status=" + status + ", cuit=" + cuit + ", branch=" + branch + ", checkout=" + checkout
+ ", terminal_number=" + terminal_number + ", intention_type=" + intention_type + ", original_amount="
+ original_amount + ", currency=" + currency + ", integrator_intention_id=" + integrator_intention_id
+ ", integrator=" + integrator + "]";
}}
All the other getter and setter,
everyone has JsonProperty in the set method
I'm working with Jackson,
so I'm sending the object with
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
ObjectResponseBimo o = objectMapper.readValue(jsonToPost, ObjectResponseBimo.class);
return objectMapper.toString() + "\n" + o.toString();
The output is:
ObjectResponseBimo [intention_id=0, intention_datetime=null,
status=null, cuit=20-314559999-9, branch=Avellaneda 13, checkout=8,
terminal_number=87980012, intention_type=payment,
original_amount=1200.0, currency=ARS,
integrator_intention_id=587cba61-ff27-46c6-ba8b-fd936665c35f,
integrator=null ]
The code you provided works fine. I have just copied it to the clean project and tested it.
I would give you couple of notes, not related to the question.
Class variables should be private, and for Jackson no need to have setters and getters to make json. It used reflection.
Class variables should be CamelCase. This is general practice in Java.
This is is, how your data class should look like:
public class ObjectResponseBimo {
#JsonProperty("intention_id")
private int intentionId;
#JsonProperty("intention_datetime")
private String intentionDatetime;
private String status;
private String cuit;
private String branch;
private String checkout;
#JsonProperty("terminal_number")
private String terminalNumber;
#JsonProperty("intention_type")
private String intentionType;
#JsonProperty("original_amount")
private double originalAmount;
private String currency;
#JsonProperty("integrator_intention_id")
private String integratorIntentionId;
private String integrator;
}
And to work with json, you could use a tool to hide all routinse. E.g. JacksonUtils:
ObjectResponseBimo obj = JacksonUtils.readValue(json, ObjectResponseBimo.class);
P.S. Repeat, code that you have provided works fine on the clean project. Probably you have a problem someqhere else, and this is only the side effect.
So I just tried to copy your code and made couple of changes.
Add below annotation at the top of your pojo class (ObjectResponseBimo.java)
**#JsonIgnoreProperties(ignoreUnknown = true)**
public class ObjectResponseBimo {
This will ignore the unknown properties from json having no match with equivalent java properties.
And for the object mapper, below snippet should be enough to get it work:
ObjectMapper objectMapper = new ObjectMapper();
ObjectResponseBimo ob = objectMapper.readValue(ClassLoader.getSystemResourceAsStream("ObjectResponseBimo.json"), ObjectResponseBimo.class);
System.out.println(ob.toString());
System.out.println(ob.getIntention_id() + " | " + ob.getBranch());
I am not sure why toString() is not working for you. It is working for me though.

How to parse nested JSON object in java

Here is the sample JSON string. I want to parse this nested JSON object even though nested object have the same name. Some time we may have multiple levels of the nested objects. I tired with Jackson nested objects parsing but that did not work for me. After parsing the object, i want to convert that into a different format.Please help me in parsing this JSON. Thanks in advance.
{
"operator": "and",
"predicates": [
{
"operator": "and",
"predicates": [
{
"columnName": "userName",
"datatype": "string",
"input": "text",
"operand": "equal",
"value": "xxxx"
},
{
"columnName": "Age",
"datatype": "number",
"input": "number",
"operand": "greater_or_equal",
"value": "21"
}
]
},
{
"operator": "and",
"predicates": [
{
"columnName": "userName",
"datatype": "string",
"input": "text",
"operand": "not_equal",
"value": "nnn"
},
{
"columnName": "Birthday",
"datatype": "date",
"input": "date_picker",
"operand": "in",
"value": "2020-07-23,2020-07-24"
}
]
}
]
}
below is the code in java
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonProperty;
public class Predicates {
private String columnName;
private String datatype;
private String input;
private String operator;
private String value;
private String operand;
/**
*
*/
private List<Predicates> predicates;
#JsonProperty("predicates")
private void unpackNested(Map<String,Object> predicates) {
this.columnName = (String)predicates.get("columnName");
this.datatype = (String)predicates.get("datatype");
this.input = (String)predicates.get("input");
this.operator = (String)predicates.get("operator");
this.value = (String)predicates.get("value");
this.operand = (String)predicates.get("operand");
}
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public String getDatatype() {
return datatype;
}
public void setDatatype(String datatype) {
this.datatype = datatype;
}
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
public String getOperator() {
return operator;
}
public void setOperator(String operator) {
this.operator = operator;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getOperand() {
return operand;
}
public void setOperand(String operand) {
this.operand = operand;
}
public List<Predicates> getPredicates() {
return predicates;
}
public void setPredicates(List<Predicates> predicates) {
this.predicates = predicates;
}
}
Parsing
ObjectMapper mapper = new ObjectMapper();
Predicates pr = mapper.readValue(json, Predicates.class);
I don't know what you are trying to achieve with your unpackNested method. Jackson can already bind properties from your JSON to your objects and handles recursive properties just fine.
I simply removed your unpackNested method and ran your code on your provided input:
ObjectMapper mapper = new ObjectMapper();
Predicates pr = mapper.readValue(json, Predicates.class);
The object pr contains the full json including the nested child predicates. (I ran the code with jackson databind 2.11.2).
If your properties are not auto-detected, annotate your getters with #JsonProperty:
class Predicate {
// ..snip..
#JsonProperty("input")
public String getInput() {
return input;
}
#JsonProperty("predicates")
public List<Predicates> getPredicates() {
return predicates;
}
}
But apart from that, no extra steps need to be taken. Jackson can already unpack nested objects, just remove your (weird) unpackNested method and let Jackson do its job.

Nested JSON objects from Spring RestClient and Jackson

I have a rest client that will be getting JSON back from an endpoint. I would like to just get what is in the data[].
{
"responseStatus": "SUCCESS",
"responseDetails": {
"limit": 1000,
"offset": 0,
"size": 2,
"total": 2
},
"data": [
{
"id": "00P000000001M01",
"name__v": "Foo",
"status__v": [
"active__v"
],
"abbreviation__c": "F170053",
"internal_name__c": "Foo",
"therapeutic_area__c": [
"neurology__c"
],
"external_id__v": "84",
"generic_name__c": "Foo",
"scientific_name__c": null
},
{
"id": "00P000000001N01",
"name__v": "Bar",
"status__v": [
"active__v"
],
"abbreviation__c": "B333334",
"internal_name__c": "Bar",
"therapeutic_area__c": [
"bone_muscle_joint__c"
],
"external_id__v": "101",
"generic_name__c": "Bar",
"scientific_name__c": null
}
]
}
Because I will make other calls which will return different fields in the data[], I wanted to map each type to a POJO so I used #JSONProperty
#JsonIgnoreProperties(ignoreUnknown = true)
public class Product extends VBase{
private String fNumber;
private String genericName;
private String scientificName;
private String therapeuticArea;
public String getFNumber() {
return fNumber;
}
#JsonProperty("abbreviation__c")
private void unpackFNumber(Map<String,Object> abbreviation__c){
fNumber = ((Map<String,Object>)abbreviation__c.get("data")).get("abbreviation__c").toString();
}
public void setLyNumber(String fNumber) {
this.fNumber = fNumber;
}
public String getGenericName() {
return genericName;
}
#JsonProperty("generic_name__c")
private void unpackGenericName(Map<String,Object> generic_name__c){
genericName = ((Map<String,Object>)generic_name__c.get("data")).get("generic_name__c").toString();
}
public String getScientificName() {
return scientificName;
}
#JsonProperty("scientific_name__c")
private void unpackScientificName(Map<String,Object>sName){
scientificName = ((Map<String,Object>)sName.get("data")).get("scientific_name__c").toString();
}
public String getTherapeuticArea() {
return therapeuticArea;
}
#JsonProperty("therapeutic_area__c")
private void unpackTheraputicArea(Map<String,Object>tArea){
therapeuticArea=((Map<String,Object>)tArea.get("data")).get("therapeutic_area__c").toString();
}
}
I have tried various ways of just getting the data[].
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
RestTemplate restTemplate = new RestTemplate(clientHttpReq);
ResponseEntity<Product[]> response = restTemplate.exchange(url, HttpMethod.GET, request,Product[].class);
//ResponseEntity<Product[]> response = restTemplate.postForEntity(url,request,Product[].class ,parmMap);
What I have been trying to avoid is making a ResponseDetail POJO with a Data[] as a field. I know it will work but because the fields in the data[] will change based on the endpoint.
Can I use a wrapper class with a List to represent the data[] as all of the POJO will extend VBase?
Here is the exception:
Exception in thread "main" org.springframework.web.client.RestClientException: Error while extracting response for type [class [Lcom.lilly.models.Product;] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `com.lilly.models.Product[]` out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `com.lilly.models.Product[]` out of START_OBJECT token
at [Source: (PushbackInputStream); line: 1, column: 1]
Declaring a POJO class as below code, and then you can get data property from the POJO.
#Data
public class Example {
private String responseStatus;
private ResponseDetails responseDetails;
private List<Data> data;
#lombok.Data
public static class ResponseDetails {
private int limit;
private int offset;
private int size;
private int total;
}
#lombok.Data
public static class Data {
private String id;
private String name__v;
private String abbreviation__c;
private String internal_name__c;
private String external_id__v;
private String generic_name__c;
private Object scientific_name__c;
private List<String> status__v;
private List<String> therapeutic_area__c;
}
#lombok.Data
#JsonIgnoreProperties(ignoreUnknown = true)
public static class Product {
#JsonProperty("name__v")
private String fNumber;
#JsonProperty("generic_name__c")
private String genericName;
#JsonProperty("scientific_name__c")
private String scientificName;
#JsonProperty("therapeutic_area__c")
private List<String> therapeuticArea;
}
public static void main(String[] args) {
String jsonResult = "{\"responseStatus\":\"SUCCESS\",\"responseDetails\":{\"limit\":1000,\"offset\":0,\"size\":2,\"total\":2},\"data\":[{\"id\":\"00P000000001M01\",\"name__v\":\"Foo\",\"status__v\":[\"active__v\"],\"abbreviation__c\":\"F170053\",\"internal_name__c\":\"Foo\",\"therapeutic_area__c\":[\"neurology__c\"],\"external_id__v\":\"84\",\"generic_name__c\":\"Foo\",\"scientific_name__c\":null},{\"id\":\"00P000000001N01\",\"name__v\":\"Bar\",\"status__v\":[\"active__v\"],\"abbreviation__c\":\"B333334\",\"internal_name__c\":\"Bar\",\"therapeutic_area__c\":[\"bone_muscle_joint__c\"],\"external_id__v\":\"101\",\"generic_name__c\":\"Bar\",\"scientific_name__c\":null}]}";
ObjectMapper objectMapper = new ObjectMapper();
try {
Example example = objectMapper.readValue(jsonResult, new TypeReference<Example>() {
});
//you can get data[] via example.getData()
System.out.println(objectMapper.writeValueAsString(example.getData()));
List<Product> products = objectMapper.readValue(objectMapper.writeValueAsString(example.getData()), new TypeReference<List<Product>>() {
});
//you can also parse data[] as List<Product>
System.out.println(JSONObject.toJSONString(products));
} catch (IOException e) {
e.printStackTrace();
}
}
}

Json map to java object from inner - nested json property

Suppose I have JSON as follow.
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "users",
"_type": "students",
"_id": "AWAEqh945A0BWjveqnd0",
"_score": 1,
"_source": {
"college": {
"sport": {
"name": "cricket",
"category": "batsman"
}
}
}
}
]
}
}
I want to map data to College object which start from _source field.
Is there way to say to Jackson or Gson to from where mapping should start ?
in this example from _source
The Response we get from ES server.
ES server hosted on AWS.
So we suppose to communicate through ES Java API RestClient.
Is it ok Query through ES Java API QueryBuilder.
What is Recommended. ?
I used below mention way.
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(resultJson);
String sourceString = jsonNode.at("/hits/hits/0/_source").toString();
College college = objectMapper.readValue(sourceString, College.class);
You can do the following using Gson:
JSONObject object = new JSONObject(s); // s is you String Json
JSONObject hits1 = object.getJSONObject("hits");
JSONArray hits = hits1.getJSONArray("hits");
for (Object jsonObj : hits) {
JSONObject json = (JSONObject) jsonObj;
JSONObject source = json.getJSONObject("_source");
College college = new Gson().fromJson(source.getJSONObject("college").toString(), College.class);
}
You also need these two Pojos:
public class College {
private Sport sport;
public College() {
}
public Sport getSport() {
return sport;
}
public void setSport(Sport sport) {
this.sport = sport;
}
}
public class Sport {
private String name;
private String category;
public Sport() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
}

How to convert JSON objects to POJO from Gson

I am trying to convert JSON objects to POJO's with GSON.
JSON String
[
{
"automation_project": {
"user_id": null,
"name": "Untitled Project",
"updated_at": "2015-06-16T19:39:42Z",
"group_id": 764496,
"created_at": "2014-11-23T01:01:59Z",
"id": 16214
}
},
{
"automation_project": {
"user_id": null,
"name": "newintropage",
"updated_at": "2015-06-16T21:20:47Z",
"group_id": 764496,
"created_at": "2015-06-16T20:39:04Z",
"id": 29501
}
}
]
The AutomationProjectsList class used with GSON
public class AutomationProjectsList {
private List<AutomationProject> automationProject = new ArrayList<AutomationProject>();
public List<AutomationProject> getAutomationProject() {
return automationProject;
}
public void setAutomationProject(List<AutomationProject> automationProject) {
this.automationProject = automationProject;
}
#Override
public String toString() {
return "AutomationProjectsList [automationProject=" + automationProject
+ "]";
}}
Automation Project POJO
public class AutomationProject {
private Object userId;
private Integer groupId;
private Integer id;
private String name;
private String updatedAt;
private String createdAt;
public Object getUserId() {
return userId;
}
public void setUserId(Object userId) {
this.userId = userId;
}
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(String updatedAt) {
this.updatedAt = updatedAt;
}
public String getCreatedAt() {
return createdAt;
}
public void setCreatedAt(String createdAt) {
this.createdAt = createdAt;
}}
The code I'm using
JSONArray jsonArray = new JSONArray(response.getEntity(String.class));
for(int i = 0; i < jsonArray.length(); i++){
if(jsonArray.get(i) instanceof JSONObject){
JSONObject jsnObj = (JSONObject)jsonArray.get(i);
AutomationProjectsList obj = new Gson().fromJson(jsnObj.toString(), AutomationProjectsList.class);
System.out.println(obj.getAutomationProject().get(0).getId());
}
}
But it gives an exception :
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.get(ArrayList.java:429)
at br.usp.icmc.teste.ConnectionRestClient.getBrowserStackProjects(ConnectionRestClient.java:74)
at br.usp.icmc.teste.TestePrincipal.main(TestePrincipal.java:9)
Why am I receiving an IndexOutOfBoundsException exception? Where am I wrong?
Your class or your JSON are incorrect. I'd suggest your JSON is.
A JSON matching your POJO class would be:
{
"automationProjects":[
{
"user_id": null,
"name": "Untitled Project",
"updated_at": "2015-06-16T19:39:42Z",
"group_id": 764496,
"created_at": "2014-11-23T01:01:59Z",
"id": 16214
},
{
"user_id": null,
"name": "newintropage",
"updated_at": "2015-06-16T21:20:47Z",
"group_id": 764496,
"created_at": "2015-06-16T20:39:04Z",
"id": 29501
}
]
}
Notice I used the name automationProjects for the list as it makes more sense, so your class would be:
public class AutomationProjectsList {
private List<AutomationProject> automationProjects = new ArrayList<AutomationProject>();
public List<AutomationProject> getAutomationProjects() {
return automationProjects;
}
public void setAutomationProjects(List<AutomationProject> automationProjects) {
this.automationProjects = automationProjects;
}
#Override
public String toString() {
return "AutomationProjectsList [automationProject=" + automationProject
+ "]";
}
}
And finally to convert JSON to AutomationProjectsList object:
AutomationProjectsList projectsList = new Gson().fromJson(jsonArray.toString(), AutomationProjectsList.class);
Then if you want to log each project:
for(AutomationProject project : projectsList.automationProjects){
System.out.println(porject.getId());
}
In conclusion, your code seems to have the fallowing issues:
Do you have a list of lists or just a single list of projects? If the list is just one, why do you iterate jsonArray like its sub-objects are lists themselves?
If you model your class correctly on the JSON then you don't need to iterate the JSON to obtain your objects
The JSON you posted is quite weird and uneasy to use with Gson, is it a requirement or can you edit it as you please?
Hope this helps
EDIT
Since you stated you cannot change the JSON you get, then it gets a little more complex, but everything is up to modelling the classes on the JSON format. So let's start form this JSON:
[
{
"automation_project": {
"user_id": null,
"name": "Untitled Project",
"updated_at": "2015-06-16T19:39:42Z",
"group_id": 764496,
"created_at": "2014-11-23T01:01:59Z",
"id": 16214
}
},
{
"automation_project": {
"user_id": null,
"name": "newintropage",
"updated_at": "2015-06-16T21:20:47Z",
"group_id": 764496,
"created_at": "2015-06-16T20:39:04Z",
"id": 29501
}
}
]
Now, this is quite nasty, but let's see what we have here: we have an unnamed array of objects with a single attribute "automationProject" which is our actual AutomationProject Object. So in terms of structure, it is a list of objects which wrap an actual AutomationProject.
Thus you'll need to get rid of your AutomationProjectList and change it with the more meaningful AutomationProjectWrapper looking as fallows:
public class AutomationProjectsWrapper {
private AutomationProject automation_project = new AutomationProject();
public AutomationProject getAutomationProject() {
return automation_project;
}
public void setAutomationProject(AutomationProject automationProject) {
this.automation_project = automationProject;
}
#Override
public String toString() {
return "AutomationProjectsList [automationProject=" + automation_project
+ "]";
}
}
See this class is equivalent to the JSON Object:
{
"automation_project": {
"user_id": null,
"name": "Untitled Project",
"updated_at": "2015-06-16T19:39:42Z",
"group_id": 764496,
"created_at": "2014-11-23T01:01:59Z",
"id": 16214
}
}
Finally you'll have an array of such wrapper objects as your jsonArray so you can write:
AutomationProjectWrapper[] projectsList = new Gson().fromJson(jsonArray.toString(), AutomationProjectWrapper[].class);
Then to log your objects:
for(AutomationProjectWrapper wrapper : projectsList){
System.out.println(wrapper.getAutomationProject().getId());
}
EDIT 2
Sorry for the mistake, in AutomationProjectWrapper class the AutomationProject field should be named automation_project.
Fixed in code above.
According to your JSON String the value you are trying to access is :
jsonString[i].automation_project.user_id
In your code you have: obj.getAutomationProject().get(0).getId()
I think is should be: obj[i].getAutomationProject().getId()

Categories