Retrofit,Dynamic json whose fields change depending on the parameters into Gson - android

I'm using retrofit2 and I need to call an API for information. The JSON that the API gives me has dynamic fields which change depending on the parameter values.
Note that I can have any number of parameters. Below is the JSON for the parameters "1","2".
{
"data":{
"1":{
"logo":"https://s2.coinmarketcap.com/static/img/coins/64x64/1.png",
"id":1,
"name":"Bitcoin",
"symbol":"BTC",
"description":"Bitcoin (BTC) is...",
"date_added":"2013-04-28T00:00:00.000Z",
"platform":null,
"category":"coin"
}
},
"2":{
"logo":"https://s2.coinmarketcap.com/static/img/coins/64x64/1.png",
"id":1,
"name":"Bitcoin",
"symbol":"BTC",
"description":"Bitcoin (BTC) is...",
"date_added":"2013-04-28T00:00:00.000Z",
"platform":null,
"category":"coin"
}
}
I've created an interface in which I get the header and the parameter key which then I call later in retrofit to return me the info I need.
public interface CurrencyService {
#GET(ApiConstants.CRYPTOCURRENCYINFO)
Call<CurrencyService> getCurrencyById(#Header("X-CMC_PRO_API_KEY")
String appkey,
#Query("id") int[] ints);
}

public class CurrencyService {
Map<String, Data> data;
}
public class Data {
String logo;
int id;
String name;
String symbol;
String description;
String date_added;
Object platform;
String category;
}
Call<CurrencyService> getCurrencyById(#Header("X-CMC_PRO_API_KEY")String appkey, #Query("id") int[] ints);

Related

Need to post JSON as an array of objects via Retrofit while dynamically adding objects

I have to post a JSON Array of objects. The JSON sample is pasted below:
[
{
"checklistkey": "what is your age ___ and ur bd___",
"checklistvalue": "yes",
"taskId": "PMTASK-cmms-01-71-1"
},
{
"checklistkey": "how r you___? ______",
"checklistvalue": "no",
"taskId": "PMTASK-cmms-DE01-71-1"
}
]
The number of object here will be added dynamically based on the ID received in the previous request.
Now the POJO for this looks like:
public class CheckListAddRequest {
#SerializedName("taskId")
#Expose
private String taskId;
#SerializedName("checklistkey")
#Expose
private String checklistkey;
#SerializedName("checklistvalue")
#Expose
private String checklistvalue;
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public String getChecklistkey() {
return checklistkey;
}
public void setChecklistkey(String checklistkey) {
this.checklistkey = checklistkey;
}
public String getChecklistvalue() {
return checklistvalue;
}
public void setChecklistvalue(String checklistvalue) {
this.checklistvalue = checklistvalue;
}
public CheckListAddRequest(String taskId, String checklistkey, String checklistvalue) {
this.taskId = taskId;
this.checklistkey = checklistkey;
this.checklistvalue = checklistvalue;
}}
The Retrofit call for this is:
#POST("cmms")
#Headers("Content-Type: application/json")
Call<CheckListAddResponse> getCheckListAdd(#Body CheckListAddRequest checkListAddRequest,
#Header("X-Auth-Token") String token,
#Header("workspace") String workspace);
Now while added the details for creating a JSON request, I write something like:
CheckListAddRequest checkListAddRequest = new CheckListAddRequest(taskNumber, checkDesc, statusString);
Now if I have more than one object in the request, how can I send it?
This should be an array/list if its multiple and dynamic objects, you can easily change items add or remove from List and send
ArrayList< CheckListAddRequest >.
make this minor change.
#POST("cmms")
#Headers("Content-Type: application/json")
Call<CheckListAddResponse> getCheckListAdd(#Body ArrayList<CheckListAddRequest> checkListAddRequest,
#Header("X-Auth-Token") String token,
#Header("workspace") String workspace);
now pass the value in array list or list.

How do you parse json object inside a json array?

I am pretty weak with JSON, and probably have a silly question, and was wondering how to parse a JSON object placed inside a JSON array.
So, as of now, I have
public Single<Profile> doProfileApiCall() {
return Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_PROFILE)
.addHeaders(mApiHeader.getProtectedApiHeader())
.build()
.getObjectSingle(Profile.class);
To retrieve my profile params, but in my endpoints I have :
[{"Name": "this", "Email","that#gmail.com"}]
I have my endpoint set up as :
public static final String ENDPOINT_PROFILE =
BuildConfig.BASE_URL
+ "/linktojson";
which gives me the above JSON.
but the issue is the [], how do I modify this with :
public Single<Profile> doProfileApiCall() {
return Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_PROFILE)
.addHeaders(mApiHeader.getProtectedApiHeader())
.build()
.getObjectSingle(Profile.class);
such that I can use my profile.java model class which has
public class Profile {
#Expose
#SerializedName("Name")
private String name;
#Expose
#SerializedName("Email")
private String email;
etc...
}
Any idea how to go about this?
In the doProfileApiCall() method instead of .getObjectSingle use
.getJSONArraySingle(ProfileList.class)
Now create a new class ProfileList.java with the following code.
List<Profile> profileList = new ArrayList<>();
public List<Profile> getProfileList() {
return profileList;
}
public void setProfileList(List<Profile> profileList) {
this.profileList = profileList;
}
Change the returntype of the doProfileApiCall method to
public Single<ProfileList> doProfileApiCall()
Whenever you want to access the data use it with the list position 0, when in future you get more data, you can index the data accordingly.
Generally, if JSON root object is an array you should use List on Java side. In your case you have array so use related method:
return Rx2AndroidNetworking.post(ApiEndPoint.ENDPOINT_PROFILE)
.addHeaders(mApiHeader.getProtectedApiHeader())
.build()
.getObjectListSingle(Profile.class);
Rx2ANRequest source.

Deserialize json with same key but different type in android using Jackson

I am calling web-services which can have 2 types of json object in response. Now sometimes i get key profile with type String and sometimes it may have same key with type 'ProfileSubObject'. So how to manage this case? Below are my two types of object. I am using Jackson library to parse json.
1.)
{
"data": [
{
"profession": "iOS Developer",
"thanks": {
"count": 5
},
"profile": "test"
}
]
}
2.)
{
"data": [
{
"profession": "iOS Developer",
"thanks": {
"count": 5
},
"profile": {
"val1":"test1",
"val2":"test2"
}
}
]
}
Key profile have 2 different type of object based on web-service call.
Following is my data class structure.
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonIgnoreProperties(ignoreUnknown = true)
public class DataObject {
#JsonProperty("profession")
private String profession;
#JsonProperty("profile")
private ProfileObject profile;
#JsonProperty("thanks")
private ThanksObject thanks;
public String getProfession() {
return profession;
}
public ThanksObject getThanks() {
return thanks;
}
public ProfileObject getProfile() {
return profile;
}
}
And Profile class is as per below.
public class ProfileObject {
ProfileObject(){
}
ProfileObject(ProfileSubObject profileSubObject){
this.profileSubObject= profileSubObject;
}
ProfileObject(String profile){
this.profile= profile;
}
private ProfileSubObject profileSubObject;
private String profile;
public ProfileSubObject getProfileSubObject() {
return profileSubObject;
}
}
Now when i parse my object, ProfileObject is always null. I want it to get parsed based on proifle key data type.
Anyone could help me with parsing?
In constructing the solution, I faced two problems:
the Json structure does not match a single DataObject
the original problem of deserializing same property into differnt types of Java objects.
The first problem I solved by constructing JavaType objects which tell Jackson the generic type of the collections involved. There are two such collections: a Map, consisting of a single entry with key "data" and value of List of DataObjects
The second problem, I solved with the Jackson feature of #JsonAnySetter which directs Jackson to call a single method for all properties it doesn't recognize. For this purpose, I added #JsonIgnore to the profile variable to make sure that Jackson indeed doesn't recognize it. Now Jackson calls the same method for the two input jsons
This is the new DataObject class:
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonIgnoreProperties(ignoreUnknown = true)
public class DataObject
{
#JsonProperty("profession")
public String profession;
#JsonIgnore // forcing jackson to not recognize this property
public ProfileObject profile;
#JsonProperty("thanks")
public ThanksObject thanks;
public String getProfession() { return profession; }
public void setProfession(String p) { profession = p; }
public ThanksObject getThanks() { return thanks; }
public void setThanks(ThanksObject t) { thanks = t; }
public ProfileObject getProfile() { return profile; }
public void setProfile(ProfileObject p) { profile = p; }
#JsonAnySetter
public void setProfileFromJson(String name, Object value)
{
// if value is single String, call appropriate ctor
if (value instanceof String) {
profile = new ProfileObject((String)value);
}
// if value is map, it must contain 'val1', 'val2' entries
if (value instanceof Map) {
ProfileSubObject profileSubObject =
new ProfileSubObject(((Map<String, String>)value).get("val1"), ((Map<String, String>)value).get("val2"));
profile = new ProfileObject(profileSubObject);
}
// error?
}
}
Here is my test method, which includes the java type construction I mentioned:
public static void main(String[] args)
{
try (Reader reader = new FileReader("C://Temp/xx2.json")) {
ObjectMapper mapper = new ObjectMapper();
// type of key of map is String
JavaType stringType = TypeFactory.defaultInstance().constructType(String.class);
// type of value of map is list of DataObjects
JavaType listOfDataObject = TypeFactory.defaultInstance().constructCollectionType(List.class, DataObject.class);
// finally, construct map type with key and value types
JavaType rootMap = TypeFactory.defaultInstance().constructMapType(HashMap.class, stringType, listOfDataObject);
Map<String ,List<DataObject>> m = mapper.readValue(reader, rootMap);
DataObject do1 = m.values()
// get first (only?) value in map (it is list)
.stream().findFirst().orElse(Collections.emptyList())
// get first (only?) item in list - it is the DataObject
.stream().findFirst().orElse(null);
System.out.println(do1.profile);
System.out.println(do1.profile.profile);
System.out.println(do1.profile.profileSubObject.val1 + " " + do1.profile.profileSubObject.val2);
} catch (Exception e) {
e.printStackTrace();
}
}
This may be of help in regards to parsing JSON, use a JsonReader. It does assume you are using RESTful webservice and have already gotten a HttpURLConnection and an InputStream from the connection.
https://developer.android.com/reference/android/util/JsonReader.html

Android Retrofit2 need to send request as Key-value but the value is a json, is it possible

Like here json is the key and the value part is a json,
how to achieved this?
json:{"id": "1234","services": [{ "service_id": "123","name": "abc"},"service_id": "123","name": "abc"}] }
I might be missing something but I think following should be sufficient (assuming you have retrofit configured to use gson converter).
public class MyPojo {
private String id;
private List<Map<String, String>> services;
...
}
For sending request parameters in key value pairs use HashMap.
Here your HashMap would be like this.
HashMap< String,Object> hashMap = new HashMap<>();
hashMap.put("json",YourPojo);
YourPojo.java
public class YourPojo{
private String id;
private List<Services> services;
//other fields
//getters and setters
//Inner class
public class Services{
public String service_id;
public String name;
//Getters and setters
}
}
and then put your hashmap as a request parameter in retrofit.
Hope this helps!.

serializing json in android using gson

I have a json that looks like this
{"abcd": {
"id": 1234,
"response": "authenticated",
"key": "abrakadaba",
"userId": 5555
}}
and a class that looks like this:
public class Login
{
#SerializedName("response")
public String response;
#SerializedName("userId")
public int userId;
#SerializedName("id")
public int employeeId;
#SerializedName("key")
public String key;
}
This normally works, but not with a json that has the {"abcd": {}} before all the info i need to retrieve.
how do I handle this `"abcd" tag to find and serialize all the other values.
You'll need something to wrap the Login to coincide with the "abcd". gson/jackson/whatever is going to want to parse that first. You could create a new class that contains a Login. If that wrapper class is truly going to be throw-away then you may want to just have it parse a Map<String, Login> and then do a myParsedMap.get("abcd") to get your Login object.
here is what worked:
#SerializedName("auth")
authorization auth;
public class authorization
{
#SerializedName("response")
public String response;
#SerializedName("userId")
public int userId;
#SerializedName("Id")
public int employeeId;
#SerializedName("key")
public String key;
}

Categories

Resources