Deserialize anonymous objects - json

What am I doing wrong that the locations property isn't being deserialized?
JSON fragment from pollinglocation.googleapis.com
...
"locations":[[{"dataset_id":841,
"election_id":2,
"id":"841:100001351",
"address":{"location_name":"ROBERT S PAYNE SCHOOL",
"line1":"1201 Floyd St",
"city":"Lynchburg",
"state":"VA",
"zip":"245011913"},
"directions":"",
"polling_hours":"6 AM - 7 PM"}]],
...
Java Object
public class PollingLocation {
public PollingLocation() {
}
String status;
ArrayList<ArrayList<Anonymous>> locations;
public class Anonymous {
public Anonymous() {
}
String dataset_id;
String election_id;
String id;
Address address;
}
public class Address {
public Address() {
}
String location_name;
String line1;
String city;
String stage;
String zip;
String polling_hours;
}
}
Code that deserializes
PollingLocation obj2 = gson.fromJson(json, PollingLocation.class);

Everything.
Specifically, you can't use inner classes or collection classes.
public class PollingLocation {
public PollingLocation() {
}
String status;
Anonymous[][] locations;
}
class Anonymous {
public Anonymous() {
}
String dataset_id;
String election_id;
String id;
Address address;
}
class Address {
public Address() {
}
String location_name;
String line1;
String city;
String stage;
String zip;
String polling_hours;
}

Related

Spring Feign Client returns null nested object

I have 2 services running(Frontend, Backend). Frontend service has Feign Client to connect to Backend API service. When a request hits Frontend, through Feign client it hits Backend API.
I have an API endpoint GET /api/v1/person which returns response like below format
{
"firstName": "stack"
"lastName": "overflow",
"address" : {
"address1" : "xyz",
"address2" : "abc street",
"postalcode": "123456"
}
}
The data for the address object is populated from external API as a JSON string. But the keys are in a different format, so I am using #JsonProperty annotation in setters and getters to convert them properly.
class Person {
private String firstName;
private String lastName;
private Address address;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void setAddress(Address address) {
this.address= address;
}
public void getAddress() {
return this.address;
}
}
public class Address {
private String address1;
private String address2;
private String postalCode;
#JsonProperty("address1")
public String getAddress1() {
return address1;
}
#JsonProperty("ADD_ONE")
public void setAddress1(String address1) {
this.address1 = address1;
}
#JsonProperty("address2")
public String getAddress2() {
return address2;
}
#JsonProperty("ADD_TWO")
public void setAddress2(String address2) {
this.address2 = address2;
}
#JsonProperty("postalCode")
public String getPostalCode() {
return postalCode;
}
#JsonProperty("PST_CDE")
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
}
From the Backend API, the response looks good and as expected. But when it reached Frontend service, the address object returned as null/empty as below
{
"firstName": "stack"
"lastName": "overflow",
"address" : {}
}
Instead of using #JsonProperty in the Address class, if I rename the JSON keys and convert the JSON string to a java object, I am getting the expected response.
I am not sure why it returns empty or null when I use the #JsonProperty in the Address class and pass the response from the Backend to the Frontend service.
Note: Response object is common for both services.
Can someone please let me know, what I am missing here?
Thanks.
You should also add address attribute in your Person class, along with its getters and setters. I believe that you must be having an address class with the following attributes :
address1
address2
postalcode
Look at the code sample below.
class Person {
private String firstName;
private String lastName;
private Address address;
#JsonProperty("firstName")
public String getFirstName() {
return firstName;
}
#JsonProperty("FST_NME")
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#JsonProperty("lastName")
public String getLastName() {
return lastName;
}
#JsonProperty("LST_NME")
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void setAddress(Address address) {
this.address= address;
}
public void getAddress() {
return this.address;
}
}
The issue is resolved when I added a new Address class for the Frontend service.
Frontend Service - with no annotations set.
public class Address {
private String address1;
private String address2;
private String postalCode;
public String getAddress1() {
return address1;
}
public void setAddress1(String address1) {
this.address1 = address1;
}
public String getAddress2() {
return address2;
}
public void setAddress2(String address2) {
this.address2 = address2;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
}
Backend Service - with #JsonProperty for setters and getters to convert the JSON keys.
public class Address {
private String address1;
private String address2;
private String postalCode;
#JsonProperty("address1")
public String getAddress1() {
return address1;
}
#JsonProperty("ADD_ONE")
public void setAddress1(String address1) {
this.address1 = address1;
}
#JsonProperty("address2")
public String getAddress2() {
return address2;
}
#JsonProperty("ADD_TWO")
public void setAddress2(String address2) {
this.address2 = address2;
}
#JsonProperty("postalCode")
public String getPostalCode() {
return postalCode;
}
#JsonProperty("PST_CDE")
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
}
Since the Address class was Common for both the services, the issue occurred, where the Frontend service was not able to convert the object since the Address class attribute names are different(used #JsonProperty for setter method).
Please comment if there is anything that I missed.
Thanks all for your proper responses.

SpringBoot JSON not deserializing into my request model

I am using SpringBoot and trying to deserialize JSON like:
{
"userId": "Dave",
"queryResults": {
"id": "ABC",
"carData": {.....},
"carId": "Honda",
"status": 0,
"model": "X"
}
}
, into MyRequestModel clas:
public class MyRequestModel {
private String userId;
private String: queryResults;
}
, that is received as #RequestBody parameter in my #PostMapping method that looks like:
#PostMapping
public String postDate(#RequestBody MyRequestModel data) {
...
return "posted";
}
The above queryResults field is supposed to be stored as a CLOB in a database.
Problem I am having is that if I send this JSON to hit my endpoint (PostMapping) method, it cannot deserialize it into MyRequestModel and I get this error:
Cannot deserialize instance of java.lang.String out of START_OBJECT token
at [Source: (PushbackInputStream); line: 3, column: 18] (through reference chain: MyRequestModel["queryResults"])]
I guess the real answer to your question is: if you NEED the queryResults property to be a String, then implement a custom deserializer.
If not, then, use one of the alternatives that Jonatan and Montaser proposed in the other answers.
Implementing a custom deserializer within Spring Boot is fairly straightforward, since Jackson is its default serializer / deserializer and it provides a easy way to write our own deserializer.
First, create a class that implements the StdDeserializer<T>:
MyRequestModelDeserializer.java
public class MyRequestModelDeserializer extends StdDeserializer<MyRequestModel> {
public MyRequestModelDeserializer() {
this(null);
}
public MyRequestModelDeserializer(Class<?> vc) {
super(vc);
}
#Override
public MyRequestModel deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = p.getCodec().readTree(p);
String userId = node.get("userId").asText();
String queryResults = node.get("queryResults").toString();
MyRequestModel model = new MyRequestModel();
model.setQueryResults(queryResults);
model.setUserId(userId);
return model;
}
}
Second, mark your class to be deserialized using your custom deserializer by using the #JsonDeserialize annotation:
MyRequestModel.java
#JsonDeserialize(using = MyRequestModelDeserializer.class)
public class MyRequestModel {
private String userId;
private String queryResults;
}
It's done.
queryResults is a String on Java side but it is an Object on JSON side.
You will be able to deserialize it if you send it in as a String:
{
"userId": "Dave",
"queryResults": "foo"
}
or if you create classes that maps to the fields:
public class MyRequestModel {
private String userId;
private QueryResults queryResults;
}
public class QueryResults {
private String id;
private CarData carData;
private String carId;
private Integer status;
private String model;
}
or if you serialize it into something generic (not recommended):
public class MyRequestModel {
private String userId;
private Object queryResults;
}
public class MyRequestModel {
private String userId;
private Map<String, Object> queryResults;
}
public class MyRequestModel {
private String userId;
private JsonNode queryResults;
}
You have two options to deserialize this request:-
change the type of queryResults to Map<String, Object>, it will accepts everything as an object of key and value. (Not recommended)
public class MyRequestModel {
private String userId;
private Map<String, Object> queryResults;
}
You have to create a class that wraps the results of queryResults as an object.
class QueryResult {
private String id;
private Map<String, Object> carData;
private String carId;
private Integer status;
private String model;
public QueryResult() {}
public QueryResult(String id, Map<String, Object> carData, String carId, Integer status, String model) {
this.id = id;
this.carData = carData;
this.carId = carId;
this.status = status;
this.model = model;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Map<String, Object> getCarData() {
return carData;
}
public void setCarData(Map<String, Object> carData) {
this.carData = carData;
}
public String getCarId() {
return carId;
}
public void setCarId(String carId) {
this.carId = carId;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
}
and make the type of queryResult as shown:-
public class MyRequestModel {
private String userId;
private QueryResult queryResults;
}

JAX-RS Json response comes in one line

This is probably some basic question. I am using JAX-RS (jersey implementation) and my code is as follows.
#Path("/data")
#GET
#Produces(MediaType.APPLICATION_JSON)
public Car handlerFn(#Context HttpServletResponse res)
{
res.setStatus(HttpServletResponse.SC_OK);
Car carObject = new Car(42,"Maruthi", "Alto");
return carObject;
}
Car Entity is as follows
public class Car {
int id;
String name;
String model;
public Car() {
}
public Car(int id, String name, String model)
{
this.id=id;
this.name = name;
this.model = model;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getModel() {
return model;
}
}
The output I am getting is in one line as follows
{"id":42,"model":"Alto","name":"Maruthi"}
In place of this I want the each member in different lines as follows
{
"id": 42,
"model": "Alto",
"name": "Maruthi"
}
How can I do that?

Android - How can I access nested objects?

I know this question has been brought up quite often, but so far I didn't really find an answer...
I am trying to use Android with GSON. I want to use a JSON String to fill a Gridview but I dont know how to access the nested objects.
The JSON File:
[{'ProductCategories':[
{
'name':'Cat1', 'Product Series':[
{
'name':'ProdSeries1', 'Description':'Lorem Ipsum Bla Bla','Products':[
{
'name':'Product1','key':'value','key':'...'
},
{
'name':'Product2','key':'value','key':'...'
},
]
}
]
},
]
}]
I made 4 classes:Products,ProductSeries,ProductCatalog and ProductCategory.
example:
public class ProductCatalog {
#SerializedName("ProductCategories")
#Expose
private List<ProductCategory> productCategories = null;
public List<ProductCategory> getProductCategories() {
return productCategories;
}
public void setProductCategories(List<ProductCategory> productCategories) {
this.productCategories = productCategories;
}
}
After that I parsed the JSON with gson:
Gson gson = new Gson();
Type type = new TypeToken<List<ProductCatalog>>(){}.getType();
List<ProductCatalog> productcatalog = gson.fromJson(JSONstring,type);
Now I have a parsed list of the JSON data but dont know how to work with the nested objects like 'Product1'. I thought the getters would help, but I cant access getProductCategories() in my activity. How can I do that?
If your using Gson means This will help you
public class MainClazz {
#SerializedName("ProductCategories")
#Expose
private List<ProductCategory> productCategories = null;
public List<ProductCategory> getProductCategories() {
return productCategories;
}
public void setProductCategories(List<ProductCategory> productCategories) {
this.productCategories = productCategories;
}
}
public class Product {
#SerializedName("name")
#Expose
private String name;
#SerializedName("key")
#Expose
private String key;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
}
public class ProductCategory {
#SerializedName("name")
#Expose
private String name;
#SerializedName("Product Series")
#Expose
private List<ProductSeries> productSeries = null;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<ProductSeries> getProductSeries() {
return productSeries;
}
public void setProductSeries(List<ProductSeries> productSeries) {
this.productSeries = productSeries;
}
}
public class ProductSeries {
#SerializedName("name")
#Expose
private String name;
#SerializedName("Description")
#Expose
private String description;
#SerializedName("Products")
#Expose
private List<Product> products = null;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
}

How can I deseralize json object in java pojo class?

I have a simple JSON statement which type is very per need. like this
{
actor:{name:"kumar",mbox:"kumar#gmail.com"}
verb :"completed"
}
or
{
actor:{name:["kumar","manish"],mbox:["kumar#gmail.com","manish#gmail.com"]}
verb :{
"id" : "http://adlnet.gov/expapi/verbs/completed",
"display" : {
"en-US" : "completed"
}
}
I am using using POJO class to map this json string and pojo class code is given bleow
#JsonProperty("actor")
Actor actor;
#JsonProperty("verb")
Verb objVerb;
#JsonProperty("verb")
String verb;
public Actor getActor() {
return actor;
}
public void setActor(Actor actor) {
this.actor = actor;
}
public Verb getObjVerb() {
return objVerb;
}
public void setObjVerb(Verb objVerb) {
this.objVerb = objVerb;
}
#JsonIgnore
public String getVerb() {
return verb;
}
#JsonIgnore
public void setVerb(String verb) {
this.verb = verb;
}
public static class Actor {
String objectType;
#JsonProperty("name")
ArrayList<String> listName;
#JsonProperty("name")
String name;
#JsonProperty("mbox")
ArrayList<String> listMbox;
#JsonProperty("mbox")
String mbox;
#JsonProperty("mbox_sha1sum")
ArrayList<String> Listmbox_sha1sum;
#JsonProperty("mbox_sha1sum")
String mbox_sha1sum;
#JsonProperty("openid")
String openid;
#JsonProperty("account")
Account account;
public String getObjectType() {
return objectType;
}
public void setObjectType(String objectType) {
this.objectType = objectType;
}
public ArrayList<String> getListName() {
return listName;
}
public void setListName(ArrayList<String> listName) {
this.listName = listName;
}
#JsonIgnore
public String getName() {
return name;
}
#JsonIgnore
public void setName(String name) {
this.name = name;
}
public ArrayList<String> getListMbox() {
return listMbox;
}
public void setListMbox(ArrayList<String> listMbox) {
this.listMbox = listMbox;
}
#JsonIgnore
public String getMbox() {
return mbox;
}
#JsonIgnore
public void setMbox(String mbox) {
this.mbox = mbox;
}
public ArrayList<String> getListmbox_sha1sum() {
return Listmbox_sha1sum;
}
public void setListmbox_sha1sum(ArrayList<String> listmbox_sha1sum) {
Listmbox_sha1sum = listmbox_sha1sum;
}
#JsonIgnore
public String getMbox_sha1sum() {
return mbox_sha1sum;
}
#JsonIgnore
public void setMbox_sha1sum(String mbox_sha1sum) {
this.mbox_sha1sum = mbox_sha1sum;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public static class Account {
#JsonProperty("homePage")
String homePage;
#JsonProperty("name")
String name;
public String getHomePage() {
return homePage;
}
public void setHomePage(String homePage) {
this.homePage = homePage;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
public static class Verb {
String id;
Map<String,String> display;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Map<String, String> getDisplay() {
return display;
}
public void setDisplay(Map<String, String> display) {
this.display = display;
}
}
I am using jaxb and jakson. I am implementing the webservice to handle the json statement
so I use the bean class to map with json. But when I use to map this json then it gives the following exceptions
org.codehaus.jackson.map.JsonMappingException : property with the name "mbox" have two entry.
Define a proper bean structure so it directly mapped to the beans class
Try to leave only #JsonProperty("mbox") ArrayList<String> listMbox; field (don't need #JsonProperty("mbox")
String mbox;)
and add Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY=true to Jackson object mapper config.
So in deserialization it will be able to get as both array and single element.
you can use gson.
class cls = gson.fromJson(jsonString, clazz);
here jsonString can be stringified java script object. gson.fromJson method can map your java script key to java property.