Deserializing 2D JSON array to bean using GSON - java

I have not been able to map this nested array rows->elements to my javabean. Is gson actually capable of handling this kind of mapping? I also tried a different approach, which you can see if you look at the commented out Java code.
package scratch;
import java.util.ArrayList;
import java.util.List;
/*
{
"rows" : [
{
"elements" : [
{
"distance" : {
"text" : "897 mi",
"value" : 1443464
},
"duration" : {
"text" : "14 hours 32 mins",
"value" : 52327
},
"status" : "OK"
}
]
},
{
"elements" : [
{
"distance" : {
"text" : "378 mi",
"value" : 607670
},
"duration" : {
"text" : "6 hours 22 mins",
"value" : 22908
},
"status" : "OK"
}
]
}
]
}
*/
public class GeoZipCodesBean2 {
// private Elem[][] rows;
// public Elem[][] getRows() {
// return rows;
// }
//
// public void setRows(Elem[][] rows) {
// this.rows = rows;
// }
private List<List<Elem>>rows;
public List<List<Elem>> getRows() {
return rows;
}
public void setRows(List<List<Elem>> rows) {
this.rows = rows;
}
public static class Elem {
private Distance distance;
private Duration duration;
public Distance getDistance() {
return distance;
}
public void setDistance(Distance distance) {
this.distance = distance;
}
public Duration getDuration() {
return duration;
}
public void setDuration(Duration duration) {
this.duration = duration;
}
}
public static class Distance {
private String text;
private Integer value;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
}
public static class Duration {
private String text;
private Integer value;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
}
}
GeoZipCodesBean2 geoZipCodesBean2 = new Gson().fromJson(str, GeoZipCodesBean2.class);

This should be the JSON format for your GeoZipCodesBean2 object (if rows is a List<List<Elem>>)
{
"rows": [
[
{
"elements": [
{
"distance": {
"text": "897 mi",
"value": 1443464
},
"duration": {
"text": "14 hours 32 mins",
"value": 52327
},
"status": "OK"
}
]
},
{
"elements": [
{
"distance": {
"text": "378 mi",
"value": 607670
},
"duration": {
"text": "6 hours 22 mins",
"value": 22908
},
"status": "OK"
}
]
}
]
]
}
This is the code for converting to/from json
public static void main(String[] args) {
Gson gson = new GsonBuilder().create();
GeoZipCodesBean2 geo = new GeoZipCodesBean2();
List<List<Elem>> rows = new ArrayList<List<Elem>>();
List<Elem> elem = new ArrayList<Elem>();
Elem e1 = new Elem();
Distance d = new Distance();
d.setText("fads");
d.setValue(1234);
e1.setDistance(d);
elem.add(e1);
rows.add(elem);
geo.setRows(rows);
String json = gson.toJson(geo);
//The following prints {"rows":[[{"distance":{"text":"fads","value":1234}}]]}
System.out.println(json);
json = "{\"rows\":[[{\"distance\":{\"text\":\"fads\",\"value\":1234}, \"status\":\"OK\"}]]}";
GeoZipCodesBean2 geo2 = gson.fromJson(json, GeoZipCodesBean2.class);
//The following prints 1234
System.out.println(geo2.getRows().get(0).get(0).getDistance().getValue());
}

Related

Parsing JSON in Java returns empty result

I am trying to parse a JSON with Java and I do not get the expected result.
Example json:
"productId": "NDAtOS0wLS0=",
"branchId": 5,
"branchCustomers":[
{"branchId":615,"customerNumber":4918,"products":[]},
{"branchId":615,"customerNumber":9753,"products":[]},
{"branchId":615,"customerNumber":9761,"products":[]}
],
"customerNumber": 240,
"subAccountNumber": 0,
"productType": 9,
"openingDate": "2016-10-02",
"values": [
{
"key": "accountingMethod",
"value": "1"
},
{
"key": "accountType",
"value": "1"
},
{
"key": "assetCashAccountId-branchId",
"value": "615"
},
{
"key": "assetCashAccountId-customerNumber",
"value": "4041240"
},
{
"key": "assetCashAccountId-subAccountNumber",
"value": "2"
},
{
"key": "assetMarginAccountId-branchId",
"value": "615"
},
{
"key": "assetMarginAccountId-customerNumber",
"value": "4041240"
},
{
"key": "assetMarginAccountId-subAccountNumber",
"value": "2"
},
{
"key": "blockingAmount",
"value": "1000000"
},
{
"key": "collateral",
"value": "C"
},
{
"key": "collateralBlockingType",
"value": "1"
},
{
"key": "executingSecurityAccountId-branchId",
"value": "615"
},
{
"key": "executingSecurityAccountId-customerNumber",
"value": "4041240"
},
{
"key": "executingSecurityAccountId-subAccountNumber",
"value": "0"
},
{
"key": "limit",
"value": "1000000"
},
{
"key": "marginAccountId-branchId",
"value": "0"
},
{
"key": "marginAccountId-customerNumber",
"value": "0"
},
{
"key": "marginAccountId-subAccountNumber",
"value": "0"
},
{
"key": "marginMarkup",
"value": "100"
},
{
"key": "rolfNolanLedger",
"value": "B01429"
},
{
"key": "settlementMethod",
"value": "1"
}
]
}
]
}],
"instances": []
}
Not all the JSONs have this structure, some may miss some of the fields. I created some DTO classes for parsing it. This is my code:
public class Response {
private String partnerId;
private byte branchId;
private long customerNumber;
private Long subAccountNumber;
private Byte productType;
private String openingDate;
private String closingDate;
private List<Values> values;
private List<Instances> instances;
private List<BranchCustomers> branchCustomers;
public String getProductid() {
return partnerId;
}
public void setProductid(String productid) {
this.partnerId = productid;
}
public byte getBranchid() {
return branchId;
}
public void setBranchid(byte branchid) {
this.branchId = branchid;
}
public long getCustomernumber() {
return customerNumber;
}
public void setCustomernumber(long customernumber) {
this.customerNumber = customernumber;
}
public Long getSubaccountnumber() {
return subAccountNumber;
}
public void setSubaccountnumber(Long subAccountNumber) {
this.subAccountNumber = subAccountNumber;
}
public Byte getProducttype() {
return productType;
}
public void setProducttype(Byte productType) {
this.productType = productType;
}
public String getOpeningdate() {
return openingDate;
}
public void setOpeningdate(String openingDate) {
this.openingDate = openingDate;
}
public String getClosingdate() {
return closingDate;
}
public void setClosingdate(String closingDate) {
this.closingDate = closingDate;
}
public List<Values> getValues() {
return values;
}
public void setValues(List<Values> values) {
this.values = values;
}
public List<Instances> getInstances() {
return instances;
}
public void setInstances(List<Instances> instances) {
this.instances = instances;
}
public List<BranchCustomers> getBranchCustomers() {
return branchCustomers;
}
public void setBranchCustomers(List<BranchCustomers> branchCustomers) {
this.branchCustomers = branchCustomers;
}
}
public class BranchCustomers {
private byte branchId;
private long customerNumber;
private List<Products> products;
public byte getBranchid() {
return branchId;
}
public void setBranchid(byte branchId) {
this.branchId = branchId;
}
public long getCustomernumber() {
return customerNumber;
}
public void setCustomernumber(long customerNumber) {
this.customerNumber = customerNumber;
}
public List<Products> getProducts() {
return products;
}
public void setProducts(List<Products> products) {
this.products = products;
}
}
public void parseJson(String response) {
try{
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Response result = mapper.readValue(response, Response.class);
System.out.println(result);
} catch (JsonMappingException e) {
e.printStackTrace
} catch (JsonProcessingException e) {
e.printStackTrace();
}
The other DTO classes "Values", "Instances" and "Products" are empty at this moment, but I do not need them yet. The problem is that the "result" value has the right structure and the right fields, but they are null or 0, depending on their data type and I cannot see what I have done wrong.
Can anyone help me?
Your getters, setters have incorrect names.
As an example, in your Response object, you have getProductid, getBranchid, and getCustomernumber with similar setter methods. Your JSON however has productId, branchId, and customerNumber. They differ as you didn't use the correct capitalization. You should use camelCase, which would turn your naming to getProductId, getBranchId, and getCustomerNumber. This then matches the JSON and it will map accordingly.
This:
public class Response {
private String partnerId;
private byte branchId;
private long customerNumber;
private Long subAccountNumber;
private Byte productType;
private String openingDate;
private String closingDate;
private List<BranchCustomers> branchCustomers;
public String getProductId() {
return partnerId;
}
public void setProductId(String productid) {
this.partnerId = productid;
}
public byte getBranchId() {
return branchId;
}
public void setBranchId(byte branchid) {
this.branchId = branchid;
}
public long getCustomerNumber() {
return customerNumber;
}
public void setCustomerNumber(long customernumber) {
this.customerNumber = customernumber;
}
...
Leads to:
Response{productId='NDAtOS0wLS0=', branchId=5, customerNumber=240 ...
As a sidenote, I suggest either auto-generating the boilerplate code with your IDE or look into Project Lombok which can generate the boilerplate code by just adding an annotation. This also stops you from making naming mistakes.
Also, try and get a toString method for each pojo, as it will help you during logging or debugging.

Jackson UnrecognizedPropertyException thrown when it's there

I have a basic spring boot standalone executable jar using the bott 2.0.0.0 I think this is simple, but Google won't give up the answer. :) I am am using the latest stable jackson versions (2.9.4) but they ARE being managed by spring. This is a Boolean problem:
here is the JSON I am trying to turn into a Java Pojo (it is wrapped in a higher object but I don't think that's the problem. I haveing problems qith the boolean.
{
"guid": "a5182918-8d69-11e6-acb6-0a97227b08ed",
"organizationId": 1,
"region": "Tariff Picker",
"stages": [{
"nextStages": [],
"activities": [{
"nextActivities": [],
"name": "New Activity",
"suspensionReason": "",
"rules": [],
"isSuspend": false,
"sequence": 1,
"allowedRoles": [{
"userApplications": [],
"name": "submitApplication",
"organizationId": 0,
"workQueues": [],
"roleApplicationsForSystemRoleId": [],
"isPublic": 0,
"widgetRoles": [],
"userRoles": [],
"roleTariffReports": [],
"roleTypeId": 0,
"distributionListRoles": [],
"organizationRoles": [],
"publicationRoles": [],
"roleTariffDataSets": [],
"roleApplicationsForApplicationRoleId": [],
"workQueueArchives": [],
"id": 11,
"rolePrivileges": []
}],
"label": "New Activity",
"irrevocable": false,
"stageId": 0,
"id": 0,
"buttonPrompt": "Submit",
"guid": "2e195e0c-83d2-491f-b2e8-3ad1159d1d99",
"dataBlock": {
"sections": [{
"info": "",
"prompt": "",
"name": "First Section",
"sequence": 0,
"fields": [],
"gatingConditions": [],
"guid": "480d160c-c34f-4022-97b0-e8a1f28c49ae",
"id": -2
}],
"prompt": "",
"id": -1,
"name": ""
},
"autoExecute": false
}],
"name": "Tariff Selection Stage",
"sequence": 1,
"rules": [],
"completionMessage": "",
"guid": "65a73280-c587-486f-be8b-9107426f4730",
"id": 0,
"description": ""
}],
"stop": "3000-01-01",
"workflowTypeId": 2,
"isUserAction": false,
"start": "1900-01-01",
"isSandbox": false,
"gatingConditions": [],
"tariffId": 49,
"businessCalendarId": 1,
"applicationForms": [],
"id": 49,
"rules": []
}
I am getting an error saying there is not a field named "isSuspend" and as you can see it is there (line 3) and even set to false. here is my pojo:
private int id;
private String name;
private List<DataBlockObject> dataBlocks;
private int sequence;
private List<RuleObject> rules;
private List<AllowedRoleObject> allowedRoles;
private List<NextActivityObject> nextActivities;
private List<ActivityPermissionObject> activityPermissions;
private boolean autoExecute;
private boolean irrevocable;
private String label;
private String buttonPrompt;
private int stageId;
private boolean isSuspend;
private String suspensionReason;
private String guid;
private List<ActivitySubmitErrorPromptObject> activitySubmitErrorPrompts;
private int activitySubmitErrorTimeout;
private String breadcrumbClass;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<DataBlockObject> getDataBlocks() {
return dataBlocks;
}
public void setDataBlocks(List<DataBlockObject> dataBlocks) {
this.dataBlocks = dataBlocks;
}
public int getSequence() {
return sequence;
}
public void setSequence(int sequence) {
this.sequence = sequence;
}
public List<RuleObject> getRules() {
return rules;
}
public void setRules(List<RuleObject> rules) {
this.rules = rules;
}
public List<AllowedRoleObject> getAllowedRoles() {
return allowedRoles;
}
public void setAllowedRoles(List<AllowedRoleObject> allowedRoles) {
this.allowedRoles = allowedRoles;
}
public List<NextActivityObject> getNextActivities() {
return nextActivities;
}
public void setNextActivities(List<NextActivityObject> nextActivities) {
this.nextActivities = nextActivities;
}
public List<ActivityPermissionObject> getActivityPermissions() {
return activityPermissions;
}
public void setActivityPermissions(List<ActivityPermissionObject> activityPermissions) {
this.activityPermissions = activityPermissions;
}
public boolean isAutoExecute() {
return autoExecute;
}
public void setAutoExecute(boolean autoExecute) {
this.autoExecute = autoExecute;
}
public boolean isIrrevocable() {
return irrevocable;
}
public void setIrrevocable(boolean irrevocable) {
this.irrevocable = irrevocable;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getButtonPrompt() {
return buttonPrompt;
}
public void setButtonPrompt(String buttonPrompt) {
this.buttonPrompt = buttonPrompt;
}
public int getStageId() {
return stageId;
}
public void setStageId(int stageId) {
this.stageId = stageId;
}
public boolean isSuspend() {
return isSuspend;
}
public void setSuspend(boolean isSuspend) {
this.isSuspend = isSuspend;
}
public String getSuspensionReason() {
return suspensionReason;
}
public void setSuspensionReason(String suspensionReason) {
this.suspensionReason = suspensionReason;
}
public String getGuid() {
return guid;
}
public void setGuid(String guid) {
this.guid = guid;
}
public List<ActivitySubmitErrorPromptObject> getActivitySubmitErrorPrompts() {
return activitySubmitErrorPrompts;
}
public void setActivitySubmitErrorPrompts(List<ActivitySubmitErrorPromptObject> activitySubmitErrorPrompts) {
this.activitySubmitErrorPrompts = activitySubmitErrorPrompts;
}
public int getActivitySubmitErrorTimeout() {
return activitySubmitErrorTimeout;
}
public void setActivitySubmitErrorTimeout(int activitySubmitErrorTimeout) {
this.activitySubmitErrorTimeout = activitySubmitErrorTimeout;
}
public String getBreadcrumbClass() {
return breadcrumbClass;
}
public void setBreadcrumbClass(String breadcrumbClass) {
this.breadcrumbClass = breadcrumbClass;
}
Can the problem be because of the getter and setter names for the field isSuspend? Try naming getter and setter getIsSuspend and setIsSuspend
Your POJO doesn't follow Java Beans naming convention. If you want Jackson to not look at the getters/setters, but only fields, see this: how to specify jackson to only use fields - preferably globally

Why does GSON give me an error when parsing an array of array of objects? [duplicate]

This question already has answers here:
Why does Gson fromJson throw a JsonSyntaxException: Expected BEGIN_OBJECT but was BEGIN_ARRAY?
(2 answers)
Closed 5 years ago.
The JSON:
[{"DataContainer": {
"ShoppingDetails": [
[
{
"Value": "3",
"Name": "Price"
},
{
"Value": "XAV-13-9LO",
"Name": "Item Code"
}
],
[
{
"Value": "9",
"Name": "Price"
},
{
"Value": "WEB-13-9XH",
"Name": "Item Code"
}
]
]
}
}]
I already have a class DataContainer:
public class DataContainer extends WebResp{
#SerializedName("ShoppingDetails")
private ShoppingDetails[] shoppingDetails;
public ShoppingDetails[] getShoppingDetails() {
return shoppingDetails;
}
public void setShoppingDetails(ShoppingDetails[] shoppingDetails) {
this.shoppingDetails= shoppingDetails;
}
}
and class ShoppingDetails:
public class ShoppingDetails{
private Field[] field;
public Field[] getField() {
return field;
}
public void setField(Field[] field) {
this.field= field;
}
}
But unfortunately, I ended up with
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 61 column 10 path $[0].DataContainer.ShoppingDetails[0]
Could someone point me in the right direction as to map this JSON to a Java object using GSON?
add DataBean
use Gson to parse it
1.DataBean
public class DataBean {
private DataContainerBean DataContainer;
public DataContainerBean getDataContainer() {
return DataContainer;
}
public void setDataContainer(DataContainerBean DataContainer) {
this.DataContainer = DataContainer;
}
public static class DataContainerBean {
/**
* Value : 3
* Name : Price
*/
private List<List<ShoppingDetailsBean>> ShoppingDetails;
public List<List<ShoppingDetailsBean>> getShoppingDetails() {
return ShoppingDetails;
}
public void setShoppingDetails(List<List<ShoppingDetailsBean>> ShoppingDetails) {
this.ShoppingDetails = ShoppingDetails;
}
public static class ShoppingDetailsBean {
private String Value;
private String Name;
public String getValue() {
return Value;
}
public void setValue(String Value) {
this.Value = Value;
}
public String getName() {
return Name;
}
public void setName(String Name) {
this.Name = Name;
}
}
}
}
2.use Gson tp parse
Gson gson = new Gson();
try {
JSONArray jsonArray = new JSONArray(response);
for (int i = 0; i < jsonArray.length(); i++) {
DataBean dataBean = gson.fromJson(jsonArray.getJSONObject(i).toString(),DataBean.class);
}
} catch (JSONException e) {
e.printStackTrace();
}

How to dynamically remove duplicate JSON Object from JSON String array

I have got the JSON as below
{
"brands": [
{
"name": "ACC",
"quantity": "0",
"listedbrandID": 1,
"status": "0"
}
],
"others": [
{
"name": "dd",
"quantity": "55",
"listedbrandID": 1
},
{
"name": "dd",
"quantity": "55",
"listedbrandID": 1
}
]
}
I am trying to remove the dupcate JSON objects from the Others array
I was trying it this way
String JSON = "{
"brands": [
{
"name": "ACC",
"quantity": "0",
"listedbrandID": 1,
"status": "0"
}
],
"others": [
{
"name": "dd",
"quantity": "55",
"listedbrandID": 1
},
{
"name": "dd",
"quantity": "55",
"listedbrandID": 1
}
]
}" ;
JSONObject json_obj = new JSONObject(json);
JSONArray array = json_obj.getJSONArray("others");
HashSet<Others> map = new HashSet<Others>();
for (int k = 0; k < array.length(); k++) {
Others otherbrands = new Others();
String name = array.getJSONObject(k).getString("name");
String quantity = array.getJSONObject(k).getString("quantity");
String listedbrandID = array.getJSONObject(k).getString("listedbrandID");
if(name!=null && !name.trim().equals(""))
{
otherbrands.setName(name);
otherbrands.setQuantity(quantity);
otherbrands.setListedbrandID(listedbrandID);
map.add(otherbrands);
}
}
for (int k = 0; k < array.length(); k++)
{
String name = array.getJSONObject(k).getString("name");
System.out.println(name);
if(!map.contains(name.trim()))
{
array.remove(k);
}
}
System.out.println(json_obj);
}
}
import java.util.Arrays;
public class Others {
private String name ;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getQuantity() {
return quantity;
}
public void setQuantity(String quantity) {
this.quantity = quantity;
}
public String getListedbrandID() {
return listedbrandID;
}
public void setListedbrandID(String listedbrandID) {
this.listedbrandID = listedbrandID;
}
private String quantity ;
private String listedbrandID ;
#Override
public boolean equals (Object other)
{
if (!(other instanceof Others))
return false;
Others ob = (Others) other;
return name.equals(ob.name) &&
quantity.equals(ob.quantity);
}
#Override
public int hashCode ()
{
return Arrays.hashCode(new String[]{quantity,name});
}
}
But its printing the entire JSON
There are some issues with your code:
System.out.println(json_obj); is printing your initial JSON object, you do not seem to be iterating over the set and printing its content. Try:
for(Other other : map) System.out.println("Name : " + other.getName() + " ...");
I think you need to add listedbrandID in your equals method.
To get JSON with only the unique items, you could simply emit the resultant HashMap. Please refer to this previous SO question for more information.

Gson error occurs when I convert json to gson object Expected BEGIN_ARRAY but was BEGIN_OBJECT

I am getting following error when I convert json to gson :
E/AndroidRuntime(1142): com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 51
I have json like this :
{
"ResultCode": "0",
"ErrorMessage": null,
"Payload": [
{
"Items": [
{
"Title": "Star Wars"
},
{ … },
{ … },
{ … },
{ … },
{ … },
{ … },
{ … },
{ … },
{ … },
{ … }
]
},
{
"Items": [ … ]
},
{
"Items": [ … ]
}
]
}
I have two classes : MResult class
import java.util.List;
public class MResult{
private String ErrorMessage;
private String ResultCode;
private List<List<Item>> Payload;
public String getErrorMessage() {
return ErrorMessage;
}
public void setErrorMessage(String errorMessage) {
ErrorMessage = errorMessage;
}
public String getResultCode() {
return ResultCode;
}
public void setResultCode(String resultCode) {
ResultCode = resultCode;
}
public List<List<Item>> getPayload() {
return Payload;
}
public void setPayload(List<List<Item>> payload) {
Payload = payload;
}
}
Item class :
public class Item{
private String Title;
public String getTitle() {
return Title;
}
public void setTitle(String title) {
Title = title;
}
}
I am getting the error on this line :
MResult serviceResult = new Gson().fromJson(result,MResult.class);
You need another class to hold Items
List<Foo> Payload;
class Foo{
List<Item> Items;
}

Categories