How to access of a especific element in the response of Retrofit - java

I'm querying an API with Retrofit, where the answer is this
[
{
"Id": "BT00",
"Text": "Registrarme"
},
{
"Id": "BT01",
"Text": "Iniciar sesiĆ³n"
},
{
"Id": "BT02",
"Text": "Siguiente"
},
{
"Id": "BT03",
"Text": "Si"
},
{
"Id": "BT04",
"Text": "No"
}
]
and the body response look like this screenshot
This call is stored in a ArrayList.
#SerializedName("Id")
#Expose
private String id;
#SerializedName("Text")
#Expose
private String text;
//Getters&Setters
My answer is, how to access of elements of the response?
I tried the following ways but it does not work
apptext_id.setText(response.body().get(0).toString());
Logger.d("Body %s", response.body().get(0).toString());
Logger.d("Body %s", response.body().get(0));
the answer look like this

What you need to do to get the first element of the list is: response.body().get(0).getText();
If you need to get each item, you need to:
if (response.isSuccessful()) {
List<AppTextModel> list_elements = response.body();
for (AppTextModel item : list_elements) {
Logger.d("Body %s", item.getText()); // print every text item in list
}
}
You also need in the POJO class:
public class AppTextModel {
#SerializedName("Id")
#Expose
private String id;
#SerializedName("Text")
#Expose
private String text;
//Getters&Setters
public String getText() {
return text;
}
}

Related

Salesforce External API not deserializing

I am relativly new to salesforce and apex programming. Recently I am assigned to get data from an external api. I am receiving an object which also has another object inside the main object. the data I am suppose to receive is as follows
{
"Product_Catagories": [{
"id": "8ad08aef8534de220185400383d82def",
"name": "Product One",
"description": "Desc One",
"region": "",
"category": "Main Products",
"ProductFamily": "Main",
"RelatedProducts": "POC-B0000001",
"productfeatures": []
}, {
"id": "8ad0887e8534de2701853fff5a9b22ee",
"name": "Product Two",
"description": "Desc Two",
"region": "",
"category": "Main Products",
"ProductFamily": "Main",
"RelatedProducts": "POC-B0000002",
"productfeatures": []
}, {
"id": "8ad08aef8534de2201853ffe48fc08f6",
"name": "Product Three",
"description": "Desc Three",
"region": "",
"category": "Main Products",
"ProductFamily": "Main",
"RelatedProducts": "POC-B0000003",
"productfeatures": []
}]
}
but i am getting
Product_Catagories:[category=null, description=null, id=null, name=null, productFamily=null, productfeatures=null, region=null, relatedProducts=null]
I have defined classes in apex code but the object is coming as empty. No data is showing. The code I am using is as follows
public class POCGetCategories {
public static List<Product_Catagories> getPOCCats(){
return new List<Product_Catagories>{getPOCProducts()};
}
public class Product_Catagories {
public String id;
public String name;
public String description;
public String region;
public String category;
public String productFamily;
public String relatedProducts;
public POCProductfeature productfeatures;
}
public class POCProductfeature {
public String id;
public String name;
public String code;
public String status;
public String description;
}
private static Product_Catagories getPOCProducts(){
Product_Catagories cats = new Product_Catagories();
Http h = new Http();
String method = 'GET';
String url = 'https://externalapi';
HttpRequest req = new HttpRequest();
req.setEndpoint(url);
req.setMethod(method);
req.setTimeout(120000);
req.setHeader('Content-Type', 'application/jsson');
req.setHeader('subscription-Key','db163fc326d***');
HttpResponse res = h.send(req);
cats = (Product_Catagories)System.JSON.deserialize(res.getBody(), Product_Catagories.class);
system.debug('Data: ' + cats);
return cats;
}
}
The main response object is an object with a "Product_Catagories" key that contains an array of individual categories. The features key in each category is a list as well. Your model should look something like this:
public class ProductCatagoriesResponse {
public List<Product_Catagory> Product_Catagories;
}
public class Product_Catagory {
public String id;
public String name;
public String description;
public String region;
public String category;
public String productFamily;
public String relatedProducts;
public List<POCProductfeature> productfeatures;
}
...
ProductCatagoriesResponse cats = (ProductCatagoriesResponse)System.JSON.deserialize(res.getBody(), ProductCatagoriesResponse.class);
Also, it's spelled "category." But I'm assuming that's their typo and you just have to deal with it...

Best Way to do Object Mapping with Nested Json

Currently I'm trying to write a site that interacts with a public API using Feign and Spring.
I'm having trouble deciding how to handle the object mapping for deeply nested JSON.
Ex:
[
{
"type": "console",
"category": "Console",
"result_count": 1,
"shown_count": 1,
"result": [
{
"name": "Nintendo Switch",
"id": "nintendo-switch",
"platform": {
"name": "Nintendo",
"category": "nintendo",
"type": "platform"
},
"image": {
"url": "https://encrypted-tbn1.gstatic.com/shopping?q=tbn:ANd9GcRqJYIheMDjTE9WAHjMSW4bjh7OplS7Bep9CdsBBLWMwGdXim7xOG4&usqp=CAc",
"height": 409,
"width": 631
},
"min_price": 205,
"variations": [
{
"items": [
{
"hex_code": "#696969",
"name": "Gray",
"id": "space-gray",
"type": "color"
},
{
"hex_code": "#C0C0C0",
"name": "Silver",
"id": "silver",
"type": "color"
}
],
"name": "Color",
"type": "color"
},
{
"items": [
{
"name": "Nintendo",
"id": "nintendo",
"type": "platform"
}
],
"name": "Platform",
"type": "platform"
}
]
}
]
}
]
As of now, I have a single Java file with a class for each object in the JSON, and I've considered having the Object mapper just put everything into a HashMap. Is there a more elegant way to do this?
public class SearchResults {
private List<SearchResult> products;
private int resultCount;
private String type;
}
class SearchResult {
private String name;
private String slug;
private Image image;
}
class Image {
private String URL;
private String height;
private String width;
}
Based on the json file provided i have designed the classes and also provided the code to parse the json file to java
public class Console{
String type;
String category;
int result_count;
int show_count;
Result [] result;
}
public class Result{
String name;
String id;
Platform platform;
Image image;
int mini_price;
Variation [] variations;
}
public class Platform{
String name;
String category;
String type;
}
public class Image{
String url;
int height;
int width;
}
public class Variation{
String name;
String type;
Item [] items;
}
public class Item{
String hex_code;
String name;
String id;
String type;
}
code to parse:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
Console[] consoles = objectMapper.readValue(ResourceUtils.getFile("path of json file"), Console[].class);
logger.info("Continents -> {}",(Object)continents);
for(Console console:consoles) {
//read the data accordingly
}

Parsing nested json with Retrofit at Android

I'm using retrofit at my android application. At my webapi, there is a nested json result which i need to parse. Not nested ones are fine, but when i encountered nested one, it seems i can't parse them.
This is my json example. I've shortened it a bit but all same.
When i executed call method, it just bypassing onResponse or onFailure.
I'm thinking i made a mistake at my class file but i cant figure out what or how.
JSON:
[
{
"name": "All joined for mobile",
"selectedOnes": [
"1",
"2"
],
"lines": [
{
"details": "",
"cancelDetails": null,
"isCancel": null,
"hours": [
{
"arrivalTime": "",
"departTime": "07:15:00"
},
{
"arrivalTime": "07:30:00",
"departTime": ""
}
]
},
{
"details": "",
"cancelDetails": null,
"isCancel": null,
"hours": [
{
"arrivalTime": "",
"departTime": "07:30:00"
},
{
"arrivalTime": "07:45:00",
"departTime": ""
}
]
}
]
}
]
ParsedJsonClass.java:
public class ParsedJsonClass {
#SerializedName("name")
#Expose
private String name;
#SerializedName("selectedOnes")
#Expose
private List<String> selectedOnes = null;
#SerializedName("lines")
#Expose
private List<lines> lines = null;
public class lines {
#SerializedName("details")
#Expose
private String details;
#SerializedName("cancelDetails")
#Expose
private Object cancelDetails;
#SerializedName("isCancel")
#Expose
private Object isCancel;
#SerializedName("hours")
#Expose
private List<hours> hours = null;
public class hours {
#SerializedName("arrivalTime")
#Expose
private String arrivalTime;
#SerializedName("departTime")
#Expose
private String departTime;
}
}
}

Unable to deserialize a JSON response from SonarQube using the gson library

I'm trying to use gson to deserialize some data that I'm getting back from a SonarQube API on various code metrics. This is an example of the raw JSON coming back from the server:
{
"component": {
"id": "c5fc9d6k-e28b-4ea0-8922-df18c7e07ac1",
"key": "APP:master",
"name": "master",
"qualifier": "TRK",
"measures": [
{
"metric": "coverage",
"value": "19.9",
"periods": [
{
"index": 1,
"value": "0.09999999999999787"
},
{
"index": 2,
"value": "0.09999999999999787"
},
{
"index": 3,
"value": "0.6999999999999993"
},
{
"index": 4,
"value": "8.7"
}
]
},
{
"metric": "overall_coverage",
"value": "55.7",
"periods": [
{
"index": 1,
"value": "0.0"
},
{
"index": 2,
"value": "0.0"
},
{
"index": 3,
"value": "3.0"
},
{
"index": 4,
"value": "55.7"
}
]
},
{
"metric": "ncloc",
"value": "1089127",
"periods": [
{
"index": 1,
"value": "3835"
},
{
"index": 2,
"value": "3835"
},
{
"index": 3,
"value": "-74350"
},
{
"index": 4,
"value": "102501"
}
]
}
]
}
}
I'm attempting to deserialize it into a Component class with this code:
public Component getComponentMeasures(String componentKey, List<String> measures) throws ClientProtocolException,
IOException, JsonSyntaxException, UnsupportedOperationException, JSONException
{
HttpGet request = new HttpGet(baseURL + String.format("/api/measures/component?componentKey=%s&metricKeys=%s",
componentKey, StringUtils.join(measures, ",")));
HttpResponse response = client.execute(request);
Gson gson = new Gson();
String componenta = getJSONResponse(response);
System.out.print(componenta);
Component component = gson.fromJson(componenta, Component.class);
return component;
}
This is the Component class that I'm deserializing it into:
public class Component {
#SerializedName("id")
#Expose
private String id;
#SerializedName("key")
#Expose
private String key;
#SerializedName("name")
#Expose
private String name;
#SerializedName("qualifier")
#Expose
private String qualifier;
#SerializedName("path")
#Expose
private String path;
#SerializedName("measures")
#Expose
private Measure[] measures = null;
public String getId() {
return id;
}
public String getKey() {
return key;
}
public String getName() {
return name;
}
public String getQualifier() {
return qualifier;
}
public String getPath() {
return path;
}
public Measure[] getMeasures() {
return measures;
}
}
This Component class also contains an array of Measures which in turn contain an array of periods.
Measure Class:
public class Measure {
#SerializedName("metric")
#Expose
private String metric;
#SerializedName("value")
#Expose
private String value;
#SerializedName("periods")
#Expose
private Period[] periods = null;
public String getMetric() {
return metric;
}
public String getValue() {
return value;
}
public Period[] getPeriods() {
return periods;
}
}
Period class:
public class Period {
#SerializedName("index")
#Expose
private Integer index;
#SerializedName("value")
#Expose
private String value;
public Integer getIndex() {
return index;
}
public String getValue() {
return value;
}
}
When I run this code, the deserialized component is null. Any ideas on anything that I may be doing wrong here? Note that there is an extra parameter in the Component class, "path", that is null in the JSON. This is optional and exists in other classes which contain a collection of Component objects. In those cases, this Component object and JSON deserialize fine. I've compared the JSON side-by-side and they are identical. I only seem to have the issue when trying to deserialize a standalone component object. Any help would be greatly appreciated!
Note that your JSON document is a JSON object with a single property (the path: $.component) with a nested component, however you're trying to deserialize it as if it were the top-most object:
Component component = gson.fromJson(componenta, Component.class);
Just create another class to match the top-most single property object, say something like:
final class Response {
#SerializedName("component")
#Expose
final Component component = null;
}
And then sample code like
final Response response = gson.fromJson(componenta, Response.class);
for ( final Measure measure : response.component.measures ) {
System.out.println(measure.metric + " " + measure.value);
}
will print the following output:
coverage 19.9
overall_coverage 55.7
ncloc 1089127
Sonar has an SDK for their API that encapsulates all of this and you don't have to create your own classes, etc. I used it to get info out like you're doing. See https://docs.sonarqube.org/display/SONARQUBE45/Using+the+Web+Service+Java+client and my use of it: http://myvogonpoetry.com/wp/2013/02/21/using-the-sonar-rest-api-for-weekly-emails/

Retrofit: Parsing JSON to multiple Java objects using GSON

I'm trying to create an Photos ArrayList of Photo objects. I want to separate the Photo class from the Photos class because it's becoming unreadable. The problem is that I'm no longer getting any data back
It is worth noting that this WAS working when I had the Photo class nested in Photos class as follows:
public class Photos {
#Expose private int page;
#Expose private int pages;
#Expose private int perpage;
#Expose private String total;
#Expose private ArrayList<Photo> photo = new ArrayList<Photo>();
//helpers
public ArrayList<Photo> getPhotos(){return photo;}
public void setPhotos(ArrayList<Photo> photos){this.photo = photos;}
//want to put this in it's own class
public class Photo {
//helpers
#Override
public String toString(){
return title;
}
public String getUrl(){return url_s;}
//GSON fields
#Expose private String id;
#Expose private String owner;
#Expose private String secret;
#Expose private String server;
#Expose private int farm;
#Expose private String title;
#Expose private int ispublic;
#Expose private int isfriend;
#Expose private int isfamily;
#Expose private String url_s;
}
}
Retrofit:
new Callback<PhotosResponse>() {
#Override
public void success(PhotosResponse photosResponse, Response response) {
bus.post(new ImagesReceivedEvent(photosResponse.getPhotosObject().getPhotos()));
}
The parameters matched the JSON exactly and I received an arraylist through the following response:
public class ImagesReceivedEvent {
private ArrayList<Photo> result;
public ImagesReceivedEvent(ArrayList<Photo> result){
Log.i(TAG, "arraylist for presenter");
this.result = result;
}
public ArrayList<Photo> getResult(){return result;}
}
This is where the response was received, but no longer:
public class PhotosResponse {
#Expose private Photos photos;
#Expose private String stat;
public Photos getPhotosObject(){return photos;}
public void setPhotosObject(Photos photos) {
this.photos = photos;
}
public String getStat() {
return stat;
}
public void setStat(String stat) {
this.stat = stat;
}
}
How can I separate these classes and still get the arrayList as a response? I want to separate them because I plan on using Parcelable on each class there are some hurdles I'd need to jump over when having the inner class. Any guidance would be much appreciated! Thanks.
Edit: Here is the JSON payload:
{ "photos": { "page": 1, "pages": 10, "perpage": 100, "total": "1000",
"photo": [
{ "id": "18473086614", "owner": "130897025#N07", "secret": "b3c684c356", "server": "259", "farm": 1, "title": "My travels circa 2013. Summer days on #charlesbridge #charlesbridgeprague #prauge. upbound#upbound.net || 718-754-5850 #photographer #photography #canonphotography #canon #canondslr #canon600d #dslr #600d #travelphotography #europe #upboundonline #canonre", "ispublic": 1, "isfriend": 0, "isfamily": 0 },
{ "id": "18473090744", "owner": "131790787#N07", "secret": "2734055852", "server": "3705", "farm": 4, "title": "Untitled", "ispublic": 1, "isfriend": 0, "isfamily": 0 },
{ "id": "18473091934", "owner": "61308696#N00", "secret": "b40dbfcf15", "server": "401", "farm": 1, "title": "Climbing Acatenango", "ispublic": 1, "isfriend": 0, "isfamily": 0 },
{ "id": "18473092714", "owner": "39055811#N08", "secret": "e51f5a183b", "server": "3936", "farm": 4, "title": "DSCF1735.jpg", "ispublic": 1, "isfriend": 0, "isfamily": 0 }
] }, "stat": "ok" }
It turns out that I made a mistake on the naming convention:
#Expose private ArrayList<Photo> mPhotos = new ArrayList<Photo>();
I had renamed photo to mPhotos on the arrayList but forgot that GSON needs the EXACT names of the JSON fields (Which is originally photo). I changed it back to "photo" and now the arrayList populates on my Photos object.
I need to emphasize to myself that all fields MUST match the JSON naming convention.
Thanks.
When using Retrofit and GSON there's no way to "separate" your response into different classes, you must later do it yourself. Receive your big object with all the info, then unwrap it to the needed classes.
On a project I did I had a specific package with Wrapper classes to get responses from Retrofit, then later I'd manually map it to the Objects I actually needed. Hope it helps.

Categories

Resources