GSON throwing “Expected BEGIN_OBJECT but was STRING - json

This is Json Object
[
{
"UserId":"demouser1",
"Catagories":[
{
"CatagoryName":"Entertainment",
"Persent":"25"
},
{
"CatagoryName":"Household",
"Persent":"25"
},
{
"CatagoryName":"Movie",
"Persent":"25"
},
{
"CatagoryName":"Misc",
"Persent":"25"
}
],
"RequestId":null,
"ResponseStatus":false,
"Token":null
}
]
Used The Following approach to parse the above Json
public class CategoryEntity {
private String CatagoryName;
private String Persent;
public String getCatagoryName() {
return CatagoryName;
}
public void setCatagoryName(String catagoryName) {
CatagoryName = catagoryName;
}
public String getPersent() {
return Persent;
}
public void setPersent(String persent) {
Persent = persent;
}
}
import java.util.List;
public class Entity {
private String UserId;
public String getUserId() {
return UserId;
}
public void setUserId(String userId) {
UserId = userId;
}
public List<CategoryEntity> getListCatagories() {
return ListCatagories;
}
public void setListCatagories(List<CategoryEntity> listPMMCatagories) {
ListCatagories = listPMMCatagories;
}
public String getRequestId() {
return RequestId;
}
public void setRequestId(String requestId) {
RequestId = requestId;
}
public boolean isResponseStatus() {
return ResponseStatus;
}
public void setResponseStatus(boolean responseStatus) {
ResponseStatus = responseStatus;
}
private List<CategoryEntity> ListCatagories;
private String RequestId;
private String Token;
public String getToken() {
return Token;
}
public void setToken(String token) {
Token = token;
}
private boolean ResponseStatus;
}
And
Following approach to convert the json object to corresponding object
Gson gson =new Gson();
JsonPrimitive listCatagoriesElement= element.getAsJsonPrimitive();
System.out.println("listCatagoriesElement.getAsString()>>"+listCatagoriesElement.getAsString());
sysout prints: listCatagoriesElement.getAsString()>>[{"UserId":"user1","ListCatagories":[{"CatagoryName":"Entertainment","Persent":"25"},{"CatagoryName":"Household","Persent":"25"},{"CatagoryName":"Movie","Persent":"25"},{"CatagoryName":"Misc","Persent":"25"}],"RequestId":null,"ResponseStatus":false,"Token":null}]
Entity entity = gson.fromJson(listCatagoriesElement, Entity.class);
Any ideas how should I fix it?
Thanks!

Your class CategoryEntity is correct, but in your class Entity, the attribute ListCatagories should be called Catagories to match the name in the JSON!
Apart from that, in order to parse the JSON you'd better do something like this:
Gson gson = new Gson();
Type listType = new TypeToken<List<Entity>>() {}.getType();
List<Entity> entities = gson.fromJson(yourJsonString, listType);
So you'll have a List containing just one Entity object, and you can access the values just with:
String catagoryNameI = entities.get(0).getCatagories().get(i).getCatagoryName();
String persentI = entities.get(0).getCatagories().get(i).getPersent();
You have to do this because your whole JSON response is an array, surrounded by [ ... ], so you need to parse it into some List...

Related

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;
}

Error in parsing Json File to java object using gson parser

I am trying to parse array of json objects using gson library and I am unable to parse it because of json syntax exception. I am passing the json filepath as argument to method jsonparser.
heres the example code below that i have trouble parsing.
test.json - consists of array of objects
{
"EventRecords": [
{
"eventVersion": "2.0",
"eventSource": "aws:s3",
"awsRegion": "us-east-1",
"eventTime": "2018-05-10T17:10:01.420Z",
"eventName": "ObjectCreated:Put"
}
]
}
GsonParser.java:
public class GsonParser {
public void jsonEncoder(String filePath)
{
Gson gson = new Gson();
Type listType = new TypeToken<List<Record>>(){}.getType();
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
List<Record> records = gson.fromJson(bufferedReader, listType);
System.out.println("\n\nEventRecords\n\n" + records.toString());
}
public static void main(String[] args) throws IOException {
GsonParser obj= new GsonParser();
File f = new File("/Users/test/Desktop/test.json");
obj.jsonEncoder(f.getAbsolutePath());
}
}
Record.java:
public class Record {
String eventVersion;
String eventSource;
String awsRegion;
String eventTime;
String eventName;
public String getEventVersion() {
return eventVersion;
}
public void setEventVersion(String eventVersion) {
this.eventVersion = eventVersion;
}
public String getEventSource() {
return eventSource;
}
public void setEventSource(String eventSource) {
this.eventSource = eventSource;
}
public String getAwsRegion() {
return awsRegion;
}
public void setAwsRegion(String awsRegion) {
this.awsRegion = awsRegion;
}
public String getEventTime() {
return eventTime;
}
public void setEventTime(String eventTime) {
this.eventTime = eventTime;
}
public String getEventName() {
return eventName;
}
public void setEventName(String eventName) {
this.eventName = eventName;
}
#Override
public String toString () {
return ToStringBuilder.reflectionToString(this,ToStringStyle.MULTI_LINE_STYLE);
}
}
Error:
Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
You have object in your JSON and EventRecord is array inside that object.
Add class say EventRecords
public class EventRecords{
private List<Record> eventRecords = new ArrayList<Record>();
public List<Record> getEventRecords() {
return this.eventRecords;
}
public void setEventRecords(List<Record> records) {
this.eventRecords= records;
}
}
And change your deserialization code as
EventRecords eventRecords = gson.fromJson(bufferedReader, listType);
And to fetch the ArrayList change
List<Record> records = eventRecords.getEventRecords();

Macros dont working with POJOs (CLOSED)

i don't know what or if i'm doing it wrong, but the conversion from json to my POJOs just don't work. I'm with the dependencies updated. When i called the method "readJSONFromURL" my return always is the object with yours attributes with value NULL. All the libs are up to date. My Objects:
public class ListHall {
private List<Hall> Hall;
public void setHall(List<Hall> hall) {
this.Hall = hall;
}
public List<Hall> getHall() {
if (Hall == null) {
this.Hall = new ArrayList<Hall>();
}
return Hall;
}
}
public class Hall {
private String id;
private String name;
private Integer count;
//getter and setters here
}
My DataMappers:
data_mapper ListHall:ListHallMapper
data_mapper Hall:HallMapper
My method conversor:
public ListHall mapHall() throws IOException {
ListHallMapper returnListHallMapper = new ListHallMapper();
HallMapper hallMapper = new HallMapper();
DataMapper.createContext(Arrays.asList(returnListHallMapper,
hallMapper),
(DataMapper mapper) -> {
mapper.setReadKeyConversions(Arrays.asList(DataMapper.CONVERSION_CAMEL_TO_SNAKE));
});
return returnListHallMapper.readJSONFromURL("http://192.168.0.16:7080/integration/hall", ListHall.class,"/ListHall");
}
My output JSON:
{"ListHall":{"Hall":[{"id":"0","name":"Salão 1","count":"10"},{"id":"f6a495c1-be5e-4476-a362-5d42e572bfae","name":"Salão 3","count":"0"}]}}
My result:My LIB:
What i'm doing it wrong?

Create JSON using GSON with a colon as part of a field's name

I've created a set of classes (pojos) that need to be transformed into json. because i have a constraint that json field names adhere to a certain format, i've settled on gson as my library of choice, as it allows for annotations of field names.
so, i have json field names like asset_type, preview_image_thumbnail, etc. along with that, any metadata fields must have the format, metadata:<metadata-field-name>.
so, what this comes down to is that my metadata:tags and metadata:site annotations will not be transformed by gson, since they are not valid json field names, according to gson, at least.
all works well, except for those darned metadata field names. my goal is to have output like the following:
{
"name": "Test Remote Asset",
"description": "test-remote-asset",
"asset_type": "remote_asset",
"duration": 172360,
"stream_urls": {
"flash": "http://www.test-site.com/videos/a-video.flv",
"iphone": "http://www.test-site.com/videos/a-video.3gp",
"ipad": "http://www.test-site.com/videos/a-video.3gp",
"source_file": "http://www.test-site.com/videos/a-video.mp4"
},
"metadata:tags": "tag1,tag2,tag3",
"metadata:site": "test-site"
}
here is the exception i get when attempting to transform my class to json:
java.lang.IllegalArgumentException: metadata:tags is not a valid JSON field name.
and here is the class i want to transform:
public class RemoteAsset {
/** The video's name **/
private String name;
/** The video's description **/
private String description;
/** The video asset type **/
#SerializedName("asset_type")
private String assetType;
/** The video's duration, in milliseconds **/
private long duration;
/** The video's thumbnail preview URL **/
#SerializedName("preview_image_url")
private String previewImageUrl;
/** The video's OpenCms Structure ID **/
#SerializedName("external_id")
private String externalId;
/** The video's various streaming URLs **/
#SerializedName("stream_urls")
private StreamUrls streamUrls;
/** The video's tags, coma-separated **/
#SerializedName("metadata:tags")
private String metadataTags;
/** The video's host site **/
#SerializedName("metadata:site")
private String metadataSite;
public String getMetadataTags() {
return metadataTags;
}
public void setMetadataTags(String metadata_tags) {
this.metadataTags = metadata_tags;
}
public String getMetadataSite() {
return metadataSite;
}
public void setMetadataSite(String metadata_site) {
this.metadataSite = metadata_site;
}
public RemoteAsset() {
this.streamUrls = null;
this.assetType = null;
this.previewImageUrl = "";
this.metadataSite = "";
this.metadataTags = "";
this.externalId = "";
this.description = "";
this.duration = 0L;
this.name = "";
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public String getAssetType() {
return this.assetType;
}
public void setAssetType(ASSET_TYPE asset_type) {
this.assetType = asset_type.getTypeName();
}
public long getDuration() {
return this.duration;
}
public void setDuration(long duration) {
this.duration = duration;
}
public String getPreviewImageUrl() {
return this.previewImageUrl;
}
public void setPreviewImageUrl(String preview_image_url) {
this.previewImageUrl = preview_image_url;
}
public String getExternalId() {
return this.externalId;
}
public void setExternalId(String external_id) {
this.externalId = external_id;
}
public StreamUrls getStreamUrls() {
return this.streamUrls;
}
public void setStreamUrls(StreamUrls stream_urls) {
this.streamUrls = stream_urls;
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("RemoteAsset [name=").append(this.name)
.append(", description=").append(this.description)
.append(", assetType=").append(this.assetType)
.append(", duration=").append(this.duration)
.append(", previewImageUrl=").append(this.previewImageUrl)
.append(", externalId=").append(this.externalId)
.append(", streamUrls=").append(this.streamUrls).append("]");
return builder.toString();
}
}
The problem is that those can't be mapped directly to Java variables because you can't have a colon in a variable name. You need to use the Gson #SerializedName annotation. The following works at least in Gson version 2.2.2:
public static void main( String[] args )
{
String json = "{\"some:field\":\"foo\"}";
Gson gson = new Gson();
MyClass mc = gson.fromJson(json, MyClass.class);
json = gson.toJson(mc);
System.out.println(json);
}
class MyClass
{
// String some:field; <- You can do that!
#SerializedName("some:field")
String someField;
}
Output:
{"some:field":"foo"}

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.