I am consuming a restful API which gives me the following response on a service call,
[
{
id=123,
cloudStatusTimestamp=2019-01-21T15:45:06.823,
cloudStatusCode=null,
cloudStatusMessage=300: PDF generated successfully,
cloudStatusComments=Inbound invoice,Reference: 123
}
,{
id=436,
cloudStatusTimestamp=2019-02-21T05:45:06.423,
cloudStatusCode=null,
cloudStatusMessage=300: PDF generated successfully,
cloudStatusComments=Inbound invoice, Reference: 456
}
]
I want to parse the above response to Java object. I manually tried to convert the response to JSON by replacing '=' by ':'and enclosing key and value pairs with quotes but it didn't work because some values are having ',' in between (cloudStatusComments=Inbound invoice, Reference: 456). Please share your comments.
The format of the JSON is not correct.
the format should be like this :
[
{
"id":123,
"cloudStatusTimestamp":"2019-01-21T15:45:06.823",
"cloudStatusCode":null,
"cloudStatusMessage":"300: PDF generated successfully",
"cloudStatusComments":"Inbound invoice",
"Reference": 123
},
{
"id":436,
"cloudStatusTimestamp":"2019-02-21T05:45:06.423",
"cloudStatusCode":null,
"cloudStatusMessage":"300: PDF generated successfully",
"cloudStatusComments":"Inbound invoice, Reference: 456"
}
]
hope this helps you out
Fisrt of all your json is incorrect, it should be in this format.
[
{
"id":123,
"cloudStatusTimestamp" : "2019-01-21T15:45:06.823",
"cloudStatusCode":null,
"cloudStatusMessage":"300: PDF generated successfully",
"cloudStatusComments":"Inbound invoice",
"Reference": 123
}
,{
"id":436,
"cloudStatusTimestamp":"2019-02-21T05:45:06.423",
"cloudStatusCode":null,
"cloudStatusMessage":"300: PDF generated successfully",
"cloudStatusComments":"Inbound invoice",
"Reference": 456
}
]
Now to parse this json, create following model class and get whatever field you want.
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Example {
#SerializedName("id")
#Expose
private Integer id;
#SerializedName("cloudStatusTimestamp")
#Expose
private String cloudStatusTimestamp;
#SerializedName("cloudStatusCode")
#Expose
private Object cloudStatusCode;
#SerializedName("cloudStatusMessage")
#Expose
private String cloudStatusMessage;
#SerializedName("cloudStatusComments")
#Expose
private String cloudStatusComments;
#SerializedName("Reference")
#Expose
private Integer reference;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCloudStatusTimestamp() {
return cloudStatusTimestamp;
}
public void setCloudStatusTimestamp(String cloudStatusTimestamp) {
this.cloudStatusTimestamp = cloudStatusTimestamp;
}
public Object getCloudStatusCode() {
return cloudStatusCode;
}
public void setCloudStatusCode(Object cloudStatusCode) {
this.cloudStatusCode = cloudStatusCode;
}
public String getCloudStatusMessage() {
return cloudStatusMessage;
}
public void setCloudStatusMessage(String cloudStatusMessage) {
this.cloudStatusMessage = cloudStatusMessage;
}
public String getCloudStatusComments() {
return cloudStatusComments;
}
public void setCloudStatusComments(String cloudStatusComments) {
this.cloudStatusComments = cloudStatusComments;
}
public Integer getReference() {
return reference;
}
public void setReference(Integer reference) {
this.reference = reference;
}
}
Related
I am try to model an Api response using Jackson. The id will be the same type in all but the body will be different types.
An example response would be:
{
"responses": [
{
"id": "jobTitle",
"body": {
"jobTitle": "Software Engineer"
}
},
{
"id": "thumbnailPhoto",
"body": "base 64 bit string"
}
]
}
I have the following implementation. Is this the correct approach? If the type for body returns as a string, would the JobTitle be ignored/ null?
#JsonIgnoreProperties(ignoreUnknown = true)
public class Response
{
#JsonProperty("id")
private String id;
#JsonProperty("body")
private String photo;
#JsonProperty("body")
private JobTitle jobTitle;
// getters and setters
}
I'm no expert in this area, but I would like to share my answer here.
I don't know why you design the JSON string as an array of responses for your original question. I would suggest a better design to be a single instance of "Response" object as below:
{
"id":"response id",
"jobTitle":"title",
"img":"img b64 string"
}
Just leave the field null if not exists.
But if you insist on using the origin design, below code below coding can be achieved, but the JSON string need small changes to add "type" info Tutorial from Baeldung.
[ {
"id" : "1",
"body" : {
"type" : "jobTitle",
"jobTitle" : "job title"
}
}, {
"id" : "2",
"body" : {
"type" : "img",
"data" : "xxxxx"
}
} ]
Java coding as below:
package org.example.test4;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.util.ArrayList;
public class TestApp {
public static class Response<X extends Body> {
private String id;
private X body;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public X getBody() {
return body;
}
public void setBody(X body) {
this.body = body;
}
}
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type"
)
#JsonSubTypes({
#JsonSubTypes.Type(value = JobTitle.class, name = "jobTitle"),
#JsonSubTypes.Type(value = IMG.class, name = "img")
})
public static abstract class Body{}
public static class JobTitle extends Body{
private String jobTitle;
public String getJobTitle() {
return jobTitle;
}
public void setJobTitle(String jobTitle) {
this.jobTitle = jobTitle;
}
}
public static class IMG extends Body{
private String data;
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper om = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);;
JobTitle jt = new JobTitle();
jt.setJobTitle("job title");
System.out.println(om.writeValueAsString(jt));
IMG img = new IMG();
img.setData("xxxxx");
System.out.println(om.writeValueAsString(img));
ArrayList<Response<?>> rs = new ArrayList<Response<?>>();
Response<JobTitle> r1 = new Response<JobTitle>();
r1.setId("1");
r1.setBody(jt);
rs.add(r1);
Response<IMG> r2 = new Response<IMG>();
r2.setId("2");
r2.setBody(img);
rs.add(r2);
System.out.println(om.writeValueAsString(rs));
}
}
I have the following json from the Server. It is a json array with different objects. I want to identify the user objects based on the key "type" and add them to a user hashmap and fetch user to show information in my view containing the "payments" object. I am using gson and retrofit. TIA
"included":[
{
"id":"1",
"type":"payments",
"attributes":{
"amount_cents":100,
"amount_currency":"INR",
"description":"Test description!!",
"created_at":"2016-03-01T11:30:53Z",
"status":"paid",
"paid_at":null,
"charged_at":null,
"formatted_amount":"Rs1.00"
},
"relationships":{
"sender":{
"data":{
"id":"2",
"type":"users"
}
},
"receiver":{
"data":{
"id":"1",
"type":"users"
}
}
}
},
{
"id":"2",
"type":"users",
"attributes":{
"first_name":"Rob",
"last_name":"Thomas"
}
},
{
"id":"1",
"type":"users",
"attributes":{
"first_name":"Matt",
"last_name":"Thomas"
}
}]
My classes are
public class ActivityFeedItem implements IFeedItem {
#SerializedName("id")
String id;
#SerializedName("type")
String type;
#SerializedName("attributes")
Attributes attributes;
protected class Attributes {
double amount_cents;
String amount_currency;
String description;
String created_at;
String status;
String paid_at;
String charged_at;
String formatted_amount;
Relationships relationships;
public double getAmount_cents() {
return amount_cents;
}
public String getAmount_currency() {
return amount_currency;
}
public String getDescription() {
return description;
}
public String getCreated_at() {
return created_at;
}
public String getStatus() {
return status;
}
public String getPaid_at() {
return paid_at;
}
public String getCharged_at() {
return charged_at;
}
public String getFormatted_amount() {
return formatted_amount;
}
public Relationships getRelationships() {
return relationships;
}
}
}
and
public class UserFeedItem implements IFeedItem {
#SerializedName("id")
String id;
#SerializedName("type")
String type;
#SerializedName("attributes")
Attributes attributes;
public class Attributes {
#SerializedName("first_name")
String first_name;
#SerializedName("last_name")
String last_name;
}
}
This is pretty easy if you just put your JSON response String into a JSONArray. Then you can just access the type field and test if it's users. Like this:
JSONArray jsonArray = new JSONArray(yourServerResponseString);
for(int i=0; i<jsonArray.length(); i++) {
JSONObject object = (JSONObject) jsonArray.get(i);
String type = object.getString("type");
if(type.equals("users")) {
//add to your users HashMap
}
}
First of all create an array of objects from you JSON using GSON as below
Gson gson= new Gson();
String jsonString= yourJsonObject.getString("included");
ActivityFeedItem[] activityFeedArray=gson.fromJson(jsonString,ActivityFeedItem[].class);
Now your activityFeedArray contains all the feedItems you get in JSON. Then you can iterate through it as you would in any array and add to hashmap when type is user as below-
for(ActivityFeedItem item:activityFeedArray) {
if(item.type.equals("users")) {
//add to your users HashMap
}
}
I'm new to Java. I'm using Spring to consume a REST api that outputs JSON. With the tutorials on the Spring website I can easily have the JSON response converted to an object of my desired class. The problem is now that one of the keys in the JSON response is $id. I cannot make a variable with a dollar sign in it. I assume I should define some configuration somewhere that such a name would be converted into something acceptable. I don't know how.
My Rest request code:
protected LoginResult doInBackground(Void... params) {
try {
Log.i(TAG, "Making Login request");
//TODO: Make this a setting
final String url = "https://someurl.com/api/login";
LoginCredentials login = new LoginCredentials("foo#bar.com", "qwerty123");
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
LoginResult result = restTemplate.postForObject(url, login, LoginResult.class);
Log.d(TAG, "Got the LoginResult.");
return result;
} catch (Exception e) {
//TODO: Exception handling
Log.e(TAG, e.getMessage(), e);
}
return null;
}
The resulting JSON looks something like this:
{
"_id":{
"$id":"98765432"
},
"name":"Person Guy",
"email":"foo#bar.com",
"roles":[
"user"
],
"active":true,
"created":{
"sec":1439117849,
"usec":856000
},
"session":{
"token":"12345678",
"user_id":"98765432",
"created":{
"sec":1439134272,
"usec":0
},
"last_extended":{
"sec":1439134272,
"usec":0
},
"expires":{
"sec":1439998272,
"usec":0
}
}
}
The $id part is where things get difficult. The LoginResult class looks like this:
#JsonIgnoreProperties(ignoreUnknown = true)
public class LoginResult {
private String name;
private String email;
private MongoId _id;
/* Getters and setters */
}
The MongoId class looks like this (The JsonIgnoreProperties is now added to avoid exceptions):
#JsonIgnoreProperties(ignoreUnknown = true)
public class MongoId {
private String id; //This is $id in the JSON response.
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Any help would be largely appreciated.
You can use the #JsonProperty("$id") annotation in MongoId to tell how the JSON is mapped to your Java object:
#JsonIgnoreProperties(ignoreUnknown = true)
public class MongoId {
#JsonProperty("$id")
private String id; //This is $id in the JSON response.
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Here is a quick overview for reference.
i get a JSON response from a server and i want to transform it into a POJO which is the following:
public class MeasureDataGetPOJO {
#SerializedName("CODE")
private String code = null;
#SerializedName("USER")
private User user = null;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public class User {
private List<MeasureData> measureDatas = null;
public List<MeasureData> getMeasureDatas() {
return measureDatas;
}
public void setMeasureDatas(List<MeasureData> measureDatas) {
this.measureDatas = measureDatas;
}
public class MeasureData {
#SerializedName("MT_TIME")
private String time = null;
#SerializedName("MT_VALUE")
private String value = null;
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
}
The JSON i get from the server:
{
"CODE":"012",
"USER":
[
{
"MT_TIME":"1412882760",
"MT_VALUE":"319",
}
]
}
And the error i get from Gson is:
Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 10
Is there something wrong with the JSON or with the POJO i try to map the JSON into?
I am expecting one user with multiple pairs of MT_TIME and MT_VALUE.
So i get a status code and a user object. the user has a array of pairs of MT_TIME and MT_VALUE.
Later there maybe will be more user informations in the user object.
It is just a guess but would this be the correct json?
{
"CODE":"012",
"USER":
{
"MEASURE_DATA":
[
{
"MT_TIME":"1412882760",
"MT_VALUE":"319"
}
]
}
}
with an additional SerializedName here:
#SerializedName("MEASURE_DATA")
private List<MeasureData> measureDatas = null;
It is expected. From what your class says, the JSON should look like:
{
"CODE": "012",
"USER": {
"MT_TIME": "1412882760",
"MT_VALUE": "319",
}
}
But the user field in the JSON you showed is inside an array.
If this means that what you expect is a list of users instead of just one user, then replace your field in the POJO with a List<User>; otherwise, fix the JSON.
You need list of Users. See that after "USER": there is a [ in your json String.
This is what the error is saying:
Expected BEGIN_OBJECT but was BEGIN_ARRAY
I have a Java app that is getting back the following JSON from a 3rd party RESTful web service:
{
"widgets":[
[
{
"id":25128,
"status":"always",
"uuid":"96f62edd-fa8a-4267-8ffb-14af0d37de26"
}
],
[
{
"id":25200,
"status":"always",
"uuid":"78553c9e-398f-495a-8fb8-ada0fb297844"
}
],
[
{
"id":25128,
"status":"never",
"uuid":"b1e3deb2-a842-4cba-8272-458d15efb394"
}
]
]
}
And trying to convert it into a List<Widget> using GSON:
public class Widget {
#SerializedName("id")
private Long id;
#SerializedName("status")
private String status;
#SerializedName("uuid")
private String uuid;
// Getters & setters, etc.
}
Here is my mapper code:
String jsonResponse = getJsonFromWebService();
Gson gson = new Gson();
List<Widget> widgets = gson.fromJson(jsonResponse, new TypeToken<List<Widget>>(){}.getType());
When I run this, I'm getting the following error:
java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2
java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2
Obviously, I either need to manipulate the JSON string before sending it to my GSON mapper code, or I need to configure GSON to handle the "unexpected" JSON, but I'm not sure which is easier/more appropriate. If I need to "massage" the JSON string, not sure what I need to do to make GSON play nicely with it. And if I need to configure GSON, not sure what to do there either. Any ideas? Thanks in advance.
What's wrong is that you're ignoring the root JSON Object with a single JSON Property "widgets". Try deserializing your data into this object instead:
public class WidgetList {
#SerializedName("widgets")
private List<List<Widget>> widgets;
}
Massaging it to the below format works for me
[
{
'id':25128,
'status':'always',
'uuid':'96f62edd-fa8a-4267-8ffb-14af0d37de26' },
{
'id':25200,
'status':'always',
'uuid':'78553c9e-398f-495a-8fb8-ada0fb297844' },
{ 'id':25128,
'status':'never',
'uuid':'b1e3deb2-a842-4cba-8272-458d15efb394'
}
]
As the below demonstrates
public class TryMe {
public static void main(String[] args) {
Gson gson = new Gson();
List<Widget> widgets = gson.fromJson(json,
new TypeToken<List<Widget>>() {
}.getType());
System.out.println(widgets);
}
}
class Widget {
#SerializedName("id")
private Long id;
#SerializedName("status")
private String status;
#SerializedName("uuid")
private String uuid;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
#Override
public String toString() {
return "Widget [id=" + id + ", status=" + status + ", uuid=" + uuid
+ "]";
}
}
Giving the below resp
[Widget [id=25128, status=always, uuid=96f62edd-fa8a-4267-8ffb-14af0d37de26], Widget [id=25200, status=always, uuid=78553c9e-398f-495a-8fb8-ada0fb297844], Widget [id=25128, status=never, uuid=b1e3deb2-a842-4cba-8272-458d15efb394]]