I'm trying to figure out how to use gson to convert reddit's api response to a form I can use. After some code I use
System.out.println(response.toString());
to get output (slightly edited)
{"json": {"errors": [], "data": {"modhash": "dosiom5o6abbbb758729039f04762a05778db4aeeeacd8eb4a", "cookie": "14756159,2012-08-21T12:05:05,0971bdec35d71af4073cf56ad82fb0ae7c5fe2d1"}}}
After googling around I built the following class
class GSONClass {
private Response jsonresponse;
public Response getJsonresponse() {
return jsonresponse;
}
public void setJsonresponse(Response jsonresponse) {
this.jsonresponse = jsonresponse;
}
public static class Response {
private String[] errors;
private Data data;
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
public String[] getErrors() {
return errors;
}
public void setErrors(String[] errors) {
this.errors = errors;
}
}
public static class Data {
private String modhash = "hi";
private String cookie;
public String getCookie() {
return cookie;
}
public void setCookie(String cookie) {
this.cookie = cookie;
}
public String getModhash() {
return modhash;
}
public void setModhash(String modhash) {
this.modhash = modhash;
}
}
}
Then I use:
GSONClass target = new GSONClass();
String json = gson.toJson(response.toString());
GSONClass target = gson.fromJson(json, GSONClass.class);
I'm doing something wrong because I get a "java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING" error.
You were close. Your object needed to have an attribute named json that contained both an array(errors) and an object named data that contained properties modhash and cookie. The property you were calling jsonResponse needed to be called json.
public class GSONClass {
private Response json;
public static class Response {
private String[] errors;
private Data data;
}
public static class Data {
private String modhash = "hi";
private String cookie;
}
}
And a stub/runner.
import com.google.gson.Gson;
public class Main {
public static void main(String[] args) {
String response = "{\"json\": {\"errors\": [], \"data\": {\"modhash\": \"dosiom5o6abbbb758729039f04762a05778db4aeeeacd8eb4a\", \"cookie\": \"14756159,2012-08-21T12:05:05,0971bdec35d71af4073cf56ad82fb0ae7c5fe2d1\"}}}";
GSONClass target = new Gson().fromJson(response, GSONClass.class);
System.out.println(target);
}
}
Related
I am calling an API using rest template like below:
ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, entity, String.class);
And here is the json response string that i receive from the API
{
"data": {
"individuals": [
{
"cust_xref_id": "abf",
"cust_frd_alrt_in": "n",
"cust_satis_trd_ct": "4",
"gam_open_rv_trd_ct": "4",
"cust_extnl_delinq_90_day_ct": "1",
"cust_extnl_delinq_in": "y"
}
]
}
}
how can i map this response into a pojo? please help.
Required classes for the conversion are below,
1. DataDTO
public class DataDTO {
private IndividualList data;
public IndividualList getData() {
return data;
}
public void setData(IndividualList data) {
this.data = data;
}}
2. IndividualList
public class IndividualList {
private List<IndividualDTO> individuals;
public List<IndividualDTO> getIndividuals() {
return individuals;
}
public void setIndividuals(List<IndividualDTO> individuals) {
this.individuals = individuals;
}}
3. IndividualDTO
public class IndividualDTO {
#JsonProperty("cust_xref_id")
private String custXrefId;
#JsonProperty("cust_frd_alrt_in")
private String custFrdAlrtIn;
#JsonProperty("cust_satis_trd_ct")
private String custSatisTrdCt;
#JsonProperty("gam_open_rv_trd_ct")
private String gamOpenRvTrdCt;
#JsonProperty("cust_extnl_delinq_90_day_ct")
private String custExtnlDelinq90DayCt;
#JsonProperty("cust_extnl_delinq_in")
private String custExtnlDelinqIn;
public String getCustXrefId() {
return custXrefId;
}
public void setCustXrefId(String custXrefId) {
this.custXrefId = custXrefId;
}
public String getCustFrdAlrtIn() {
return custFrdAlrtIn;
}
public void setCustFrdAlrtIn(String custFrdAlrtIn) {
this.custFrdAlrtIn = custFrdAlrtIn;
}
public String getCustSatisTrdCt() {
return custSatisTrdCt;
}
public void setCustSatisTrdCt(String custSatisTrdCt) {
this.custSatisTrdCt = custSatisTrdCt;
}
public String getGamOpenRvTrdCt() {
return gamOpenRvTrdCt;
}
public void setGamOpenRvTrdCt(String gamOpenRvTrdCt) {
this.gamOpenRvTrdCt = gamOpenRvTrdCt;
}
public String getCustExtnlDelinq90DayCt() {
return custExtnlDelinq90DayCt;
}
public void setCustExtnlDelinq90DayCt(String custExtnlDelinq90DayCt) {
this.custExtnlDelinq90DayCt = custExtnlDelinq90DayCt;
}
public String getCustExtnlDelinqIn() {
return custExtnlDelinqIn;
}
public void setCustExtnlDelinqIn(String custExtnlDelinqIn) {
this.custExtnlDelinqIn = custExtnlDelinqIn;
}}
Tested Response:
{"data":{"individuals":[{"cust_xref_id":"abf","cust_frd_alrt_in":"n","cust_satis_trd_ct":"4","gam_open_rv_trd_ct":"4","cust_extnl_delinq_90_day_ct":"1","cust_extnl_delinq_in":"y"}]}}
This question already has answers here:
How to parse JSON in Java
(36 answers)
Closed 4 years ago.
I have the following JSON text. How can I parse it to get response-code, response, result, DISPLAYNAME ,AVAILABILITYSEVERITY, RESOURCEID , ETC?
{
"response-code":"4000",
"response":
{
"result":
[
{
"DISPLAYNAME":"Backup Server",
"AVAILABILITYSEVERITY":"5",
"RESOURCEID":"10002239110",
"TYPE":"SUN",
"SHORTMESSAGE":"Clear"
}
]
,"uri":"/json/ListAlarms"
}
}
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public static void main(String[] args) {
final String json = "{ \"response-code\":\"4000\", \"response\": { \"result\": [ { \"DISPLAYNAME\":\"Backup Server\", \"AVAILABILITYSEVERITY\":\"5\", \"RESOURCEID\":\"10002239110\", \"TYPE\":\"SUN\", \"SHORTMESSAGE\":\"Clear\" } ] ,\"uri\":\"/json/ListAlarms\" } }";
ObjectMapper mapper = new ObjectMapper();
try {
JsonNode obj = mapper.readTree(json);
System.out.println(obj.get("response-code"));
JsonNode response = obj.get("response");
JsonNode firstResult = response.get("result").get(0);
System.out.println(firstResult.get("DISPLAYNAME"));
System.out.println(firstResult.get("AVAILABILITYSEVERITY"));
System.out.println(firstResult.get("RESOURCEID"));
System.out.println(firstResult.get("TYPE"));
System.out.println(firstResult.get("SHORTMESSAGE"));
System.out.println(response.get("uri"));
} catch (IOException e) {
e.printStackTrace();
}
}
output
"4000"
"Backup Server"
"5"
"10002239110"
"SUN"
"Clear"
"/json/ListAlarms"
another approach only if the json has fixed structure, is to build objects to represent the json structure and use jackson to cast that json to a java object, like
class JsonObj {
#JsonProperty("response-code")
private long responseCode;
private ResponseObj response;
public long getResponseCode() {
return responseCode;
}
public void setResponseCode(long responseCode) {
this.responseCode = responseCode;
}
public ResponseObj getResponse() {
return response;
}
public void setResponse(ResponseObj response) {
this.response = response;
}
}
class ResponseObj {
private ArrayList<ResultObj> result;
private String uri;
public ArrayList<ResultObj> getResult() {
return result;
}
public void setResult(ArrayList<ResultObj> result) {
this.result = result;
}
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
}
class ResultObj {
#JsonProperty("DISPLAYNAME")
private String displayName;
#JsonProperty("TYPE")
private String type;
#JsonProperty("AVAILABILITYSEVERITY")
private int availabilitySeverity;
#JsonProperty("RESOURCEID")
private String resourceId;
#JsonProperty("SHORTMESSAGE")
private String shortMessage;
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getAvailabilitySeverity() {
return availabilitySeverity;
}
public void setAvailabilitySeverity(int availabilitySeverity) {
this.availabilitySeverity = availabilitySeverity;
}
public String getResourceId() {
return resourceId;
}
public void setResourceId(String resourceId) {
this.resourceId = resourceId;
}
public String getShortMessage() {
return shortMessage;
}
public void setShortMessage(String shortMessage) {
this.shortMessage = shortMessage;
}
}
and then, access the values like that
JsonObj jsonObj = mapper.readValue(json, JsonObj.class);
System.out.println(jsonObj.getResponseCode());
ResponseObj response = jsonObj.getResponse();
ResultObj firstResult = response.getResult().get(0);
System.out.println(firstResult.getDisplayName());
System.out.println(firstResult.getAvailabilitySeverity());
System.out.println(firstResult.getResourceId());
System.out.println(firstResult.getType());
System.out.println(firstResult.getShortMessage());
System.out.println(response.getUri());
the output is the same...
Here is my API
http://services.groupkt.com/country/get/all
I'm confused on how to use the Json reader methods. I tried looking on its Javadoc, it seems the straightforward but when I implement it, it has different behavior.
Here is my code
RestResponse result = null;
String countryName = null;
String alpha2Code = null;
String alpha3Code = null;
jsonReader.beginObject();
jsonReader.beginArray();
while (jsonReader.hasNext()) {
countryName = jsonReader.nextString();
alpha2Code = jsonReader.nextString();
alpha3Code = jsonReader.nextString();
}
jsonReader.endArray();
jsonReader.beginArray();
while (jsonReader.hasNext()) {
jsonReader.beginObject();
while (jsonReader.hasNext()) {
jsonReader.skipValue();
jsonReader.peek();
}
jsonReader.endObject();
}
jsonReader.endArray();
This is my code for learning how does it navigates my json. This code runs on the read method of TypeAdapter.
Can you provide me samples on how can I easily understand how to use json reader methods correctly?
If you want to learn basic jSON parsing you should definitely read this Android Json Parsing ..... but in retrofit 2 you can use Model classes rather than json parsing.....I'm sharing my code below....
Model Class
public class WeatherResponse {
#SerializedName("cod")
#Expose
private String cod;
#SerializedName("message")
#Expose
private Double message;
#SerializedName("cnt")
#Expose
private Double cnt;
#SerializedName("list")
#Expose
private List<cityList> list = null;
#SerializedName("city")
#Expose
private City city;
public String getCod() {
return cod;
}
public void setCod(String cod) {
this.cod = cod;
}
public Double getMessage() {
return message;
}
public void setMessage(Double message) {
this.message = message;
}
public Double getCnt() {
return cnt;
}
public void setCnt(Double cnt) {
this.cnt = cnt;
API Client
public class ApiClient {
private static final int TIME_OUT = 30;
public static final String BASE_URL = "http://api.openweathermap.org/";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
if (retrofit==null) {
OkHttpClient.Builder okBuilder = new OkHttpClient.Builder();
okBuilder.connectTimeout(TIME_OUT, TimeUnit.SECONDS);
okBuilder.readTimeout(TIME_OUT, TimeUnit.SECONDS);
okBuilder.writeTimeout(TIME_OUT, TimeUnit.SECONDS);
Gson gson = new GsonBuilder().create();
return new Retrofit.Builder()
.baseUrl(BASE_URL) .addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.client(okBuilder.build())
.build();
}
return retrofit;
}
}
API Interface
public interface ApiInterface {
#GET("data/2.5/forecast?id=524901")
Call<WeatherResponse> getWeatherData(#Query("APPID") String apiKey);
}
Be easy, just try GSON. There are many examples, articles about that
https://guides.codepath.com/android/Consuming-APIs-with-Retrofit#overview
https://medium.freecodecamp.com/rxandroid-and-retrofit-2-0-66dc52725fff#.ymmfqdi9s
https://zeroturnaround.com/rebellabs/getting-started-with-retrofit-2/
According http://services.groupkt.com/country/get/all response here is GSON models
public class County {
#SerializedName("name") public String name;
#SerializedName("alpha2_code") public String alpha2Code;
#SerializedName("alpha3_code") public String alpha3Code;
}
public class RestResponse {
#SerializedName("messages") public Messages messages;
#SerializedName("result") public Countries counties;
}
public class CountriesResponse {
#SerializedName("RestResponse") public RestResponse restResponse;
}
public interface GroupktApi {
#GET("/country/get/all")
Call<CountriesResponse> getAllCountries()
}
public Gson provideGson() {
return new GsonBuilder().registerTypeAdapter(Messages.class, MessagesDeserializer());
}
public class MessagesDeserializer extend JsonDeserializer<Messages> {
#Override public Messages deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
List<String> messages = new ArrayList();
if (json.isJsonArray()) {
Type listType = new TypeToken<ArrayList<String>>(){}.getType();
List<String> arrayMessages = context.deserialize<List<String>>(value, listType)
messages.addAll(arrayMessages)
} else {
String message = json.asString()
messages.add(message)
}
return new Messages(messages);
}
}
public class Messages {
public List<String> messages;
public Messages (List<String> messages) {
this.messages = messages;
}
}
Countries in the same way
That's it
I'm new to GSON and have been having trouble parsing the JSON below. The parsing works fine until it gets to the list of bills (staring at "0":). At that point I get a null reference in the resulting gson.fromJson object. If those bills were specified in a JSON array I think it would be easy, but they're not and I can't change that. What is the best way to handle this situation?
{
"status":"OK",
"masterlist":{
"session":{
"session_id":1007,
"session_name":"97th Legislature"
},
"0":{
"bill_id":446875,
"number":"HB4001"
},
"1":{
"bill_id":446858,
"number":"HB4002"
},
"2":{
"bill_id":446842,
"number":"HB4003"
},...
This is the code in my main method:
InputStream source = retrieveStream(url);
Gson gson = new Gson();
Reader reader = new InputStreamReader(source);
ResponseData response = gson.fromJson(reader, ResponseData.class);
And this is the ResponseData class:
public class ResponseData {
private String status;
private MasterList masterlist;
public static class MasterList{
private Session session;
private Bill bill; //Also tried: Map<String, String> bill;
}
public static class Session{
private String session_id;
private String session_name;
}
public static class Bill{
private String bill_id;
private String number;
}
}
You can map the object as below:
declare an object to map with json string
public class ResponseData {
private String status;
private Map<String, MasterList> masterlist;
public Map<String, MasterList> getMasterlist() {
return masterlist;
}
public void setMasterlist(Map<String, MasterList> masterlist) {
this.masterlist = masterlist;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public static class MasterList {
private String session_id;
private String session_name;
private String bill_id;
private String number;
public String getSession_id() {
return session_id;
}
public void setSession_id(String session_id) {
this.session_id = session_id;
}
public String getSession_name() {
return session_name;
}
public void setSession_name(String session_name) {
this.session_name = session_name;
}
public String getBill_id() {
return bill_id;
}
public void setBill_id(String bill_id) {
this.bill_id = bill_id;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}
}
And use it as below:
String data = "{\"status\":\"OK\",\"masterlist\":{ \"session\":{ \"session_id\":1007, \"session_name\":\"97th Legislature\" }, \"0\":{ \"bill_id\":446875, \"number\":\"HB4001\" }, \"1\":{ \"bill_id\":446858, \"number\":\"HB4002\" }, \"2\":{ \"bill_id\":446842, \"number\":\"HB4003\" }}}";
Gson gson = new Gson();
ResponseData response = gson.fromJson(data, ResponseData.class);
for (Iterator<Entry<String, MasterList>> it = response.getMasterlist().entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, MasterList> entry = it.next();
System.out.println(entry.getKey());
System.out.println(entry.getValue().getSession_id());
}
I'm being given a Json file with the form:
{
"descriptions": {
"desc1": "someString",
"desc2": {"name":"someName", "val": 7.0}
}
}
I have the POJO:
public class CustomClass {
Map<String, Object> descriptions;
public static class NameVal{
String name;
double val;
public NameVal(String name, double val){...}
}
}
I can recreate the json file with the code:
CustomClass a = new CustomClass();
a.descriptions = new HashMap<String, Object>();
a.descriptions.put("desc1", "someString");
a.descriptions.put("desc2", new CustomClass.NameVal("someName", 7.0));
new ObjectMapper().writeValue(new File("testfile"), a);
But, when I read the object back in using:
CustomClass fromFile = new ObjectMapper().readValue(new File("testfile"), CustomClass.class);
then fromFile.descriptions.get("desc2") is of type LinkedHashMap instead of type CustomClass.NameVal.
How can I get Jackson to properly parse the type of the CustomClass.NameVal descriptors (other than making some class that wraps the parsing and explicitly converts the LinkedHashMap after Jackson reads the file)?
Try this. Create a class Description with name and value attributes:
public class Description {
private String name;
private double val;
}
Now in your CustomClass do this:
public class CustomClass {
List<Description> descriptions;
}
And that's it. Remember to create getters and setters because Jackson needs it.
You could try something like this:
public class DescriptionWrapper {
private Description descriptions;
public Description getDescriptions() {
return descriptions;
}
public void setDescriptions(Description descriptions) {
this.descriptions = descriptions;
}
}
public class Description {
private String desc1;
private NameValue desc2;
public String getDesc1() {
return desc1;
}
public void setDesc1(String desc1) {
this.desc1 = desc1;
}
public NameValue getDesc2() {
return desc2;
}
public void setDesc2(NameValue desc2) {
this.desc2 = desc2;
}
}
public class NameValue {
private String name;
private double val;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getVal() {
return val;
}
public void setVal(double val) {
this.val = val;
}
}