Retrofit - Convert Json response to easily store data with Room - android

Is it possible to convert this :
{
"news": [
{
"nid": 1,
"type": "test1",
},
{
"nid": 2,
"type": "test2",
}
]
}
To this when I receive the result with Retrofit ?
{
"nid": 1,
"type": "test1",
},
{
"nid": 2,
"type": "test2",
}
Actually in my model, I have a NewsList object with a List of News inside (with value inside : nid, type).
And the Retrofit query looks like this :
#GET("test/test.json")
suspend fun getListNews(): Response<Newslist>
Everything is working fine, but now I need to save that data in a database with Room and it will be easier if the Retrofit query was like this :
#GET("test/test.json")
suspend fun getListNews(): Response<List<News>
What is the best way to achieve this ?
Convert Json response to get something like above ?
Keep things like this and Convert the NewsList to be able to be stored in the Room Database ?

The best way is to use RXJava or Coroutine of Kotlin.
In RXJava you can use map operator to transform your response object to list of objects.
Please refer below link to get some idea of using RXJava with retrofit and transforming results:
https://www.journaldev.com/20433/android-rxjava-retrofit

The best way is to have your backend server return the canonical json data.
If this is not possible, you can customize the converterFactor by addConverterFactory method,compatible with this data format in a custom converterFactor.

first, you must to have one layer for data provider to provide for consumer (activity, VM, fragment, etc).
in this layer, you have use case to define data collection from Cloud(Retrofit) or from Local Storage(Room). more info, i have sample here

Yes, you can, using data classes, you just need to create a data class called news with a list of items with "nid" and "type", in that cases I use a plugging of Android Studio Called Kotlin data class File from JSON

I think the better way is to return NewsList object, because it makes you easier to compatible with new feature update, like adding more fields to NewsList object. You can create a new layer for saving your data to room database, and convert the raw data to List for saving it.

Related

APis Retrofit GSON: Datatypes changing all the time

I am using Retrofit with GSON for an app for a client, and I am having some trouble with some of my client APIs and I need to workaround this problem.
Let's say i have an API which gives me telephones:
{
"telephones": [
{"phoneNumber": "1234567890"},
{"phoneNumber": "2123456789"}
]
}
But my client decided if there is only one telephone i am sending you:
{
"telephones":
{"phoneNumber": "1234567890"}
}
And when there is no telephone:
{
"telephones": "No telephone Available"
}
Is there any workaround i can make with Kotlin to solve this datatype problem?
In iOS I could force them reimplementing the Coding method and force them to always have an array. Is it possible to do something similar in Kotlin?
This is a small example, since the original answer has between 600 and 1300 lines of JSON data.
This might work.
I have done this in many places in my app.
So, the first thing, let's say you receive multiple different telephone numbers in one JSON file and might look something like this.
install a plugin call JSON to Kotlin Class
once done, make a new file using "Kotlin data class file from JSON"
the plugin for me creates automatically appropriate files.
then I use the main file to capture the data, this has worked for me almost everytime.
And yes, my other answer was if you are doing everything manually, while retrieving the data make a data class such as:
This is just for explanation purposes.
//lets say your json looks something like this
"records": [
{
"id": "1",
"telephones": [
{"phoneNumber": "1234567890"},
{"phoneNumber": "2123456789"}
]
},
{
"id": "2",
"telephones":
{"phoneNumber": "1234567890"}
},
{
"id": "3",
"telephones": "No telephone Available"
}
]
my example code would look something like this.
data class records(
//some id
val id: Int,
var telephones: List<Long>
)
so, now check inside telephones how many elements are there and add them to the list one by one.

Android. How to parse JsonArrays inside JsonArray

I use retrofit and json. I need to parse a json like that:
{
"outer_array": [
"one" : [{}, {}],
"two" : [{}],
"three" : [{}],
....
]
}
Here is part of my code:
#SerializedName("outer_array") var data: List<List<Data>>
But how can I parse each element of the "outer_array" array by key. Arrays inside "outer_array" can be from 0 to n. Maybe I should use a TypeAdapter. But I don't know how to apply it for this case, please help me
The JSON you've provided is not valid. You can check it on JSONLint. I guess it should be either an array (without "one" :) or an object ([ in front of outer_array should be {) in the first case your code is fine and in second case you can use a Map (like HashMap) and if you need to convert that map to array you can use something like this
data class MyClass(
#SerializedName("outer_array") var data: HashMap<String, List<Data>>
){
val dataAsArray get() = data.map{ it.value }
}
But if you have to parse this invalid data (e.g you cannot ask the provider/backend to fix this) even a TypeAdapter cannot help, because the JSON is invalid and you'll face an exception, you can use a regex to replace invalid [ ] with { } (but this is so dumb, try to convince the backend dev to fix the json :D)
I suggest you to use Gson, a Google service to parse JSON strings into Objects and viceversa. Simple add "implementation 'com.google.code.gson:gson:2.8.6'" into dependencies in the app's Gradle file in your Android project.
You could use two methods: toJson(Object obj) and fromJson(string json, Class<>)
if you have a class called 'MyObject', you have to put as second parameter of 'fromJson': MyObject.class, or MyObject[].class if an array.
GitHub: https://github.com/google/gson

Get particular key value from json in android (kotlin)

I'm beginner in android (Kotlin).I am getting the Following json from the HTTP Response.
{
"status": 1,
"userDetails": [
{
"AL_ID": "2",
"User_Id": "admin",
"User_Password": "admin",
"Created_Date": "2020-07-30 11:23:55"
}
],
"lastlogin": "2020-08-20 12:29:47"
}
I want to get status value from this json. How to get it.
You can use the built-in JSONObject and do something as shown below.
val json = JSONObject(jsonString) // String instance holding the above json
val status = json.getInt("status")
Having said that, I'd recommend you to take a look at Gson (for JSON serialization and deserialization) and Retrofit (an HTTP client for Android).
I would suggest using Gson library too, for android development in kotlin.
Also I would suggest to have the same DATA classes in kotlin as in database. In that way you can map objects fromJson and toJson with one line of code.
I found article that explains in details how to use Gson library with kotlin.
https://medium.com/#hissain.khan/parsing-with-google-gson-library-in-android-kotlin-7920e26f5520

Retrofit to parse json with an indefinite number of object names

I'm using retrofit to handle rest-api calls.
I have a rest API that returns the following json
"MyObject": {
"43508": {
"field1": 4339,
"field2": "val",
"field3": 15,
"field4": 586.78
},
"1010030": {
"field1": 1339,
"field2": "val212",
"field3": 1,
"field4": 86.78
},...
}
Please notice that the object MyObject contains objects with a name that is actually an id.
For all the other rest APIs I'm using retrofit without problems.
In this case it seems not possible to use the standard approach: defining a class containing the fields expected in the response.
Is there a way to transform this json into a json containing an array of
{
"field1": xxx,
"field2": "yyy",
"field3": www,
"field4": zzz
}
Or is there a better way to deal with this problem without going back to "manually" parsing the json?
Try to use next approach:
public class Response {
Map<String, YourObject> MyObject;
// getter, setter
}
public interface GitHubService {
#GET("some_path")
Call<Response> listMyObjects();
}
All you objects will be parsed to Map. You can get the list of all ids via keySet() method or list all entries with entrySet().
Try putting the annotation, SerializedName(nameOfField) over the variable name.
#SerializedName("13445345")
MyObject object;
Well my idea is quite manual, but it should work. I will not copy and paste another person's answer here, so take a look at this answer to see how to loop through all of the myObject's keys. Then for each of those keys, make a new JSONArray and add key value pair of fieldX-valueX.
This is just a basic idea, since I think you can handle the code yourself, you seem like a guy who knows his way around the simple stuff.

Retrofit, how to parse JSON objects with variable keys

First I know my title is bad as I didn't come up with better, I'm opened to suggestion.
I'm using retrofit to get data from an api of this kind : #GET("users/{userid}")
It works fine and I'm happy with it, the problem is when I call the same api with #POST("users/widget") with a list of ids. I have the following answer :
{
"long_hash_id": {
"_id": "long_hash_id"
.......
},
"long_hash_id": {
"_id": "long_hash_id",
.....
},
........
}
the "long_hash_id" is typicaly "525558cf8ecd651095af7954"
it correspond to the id of the user attached to it.
When I didn't use retrofit, I used Gson in stream mode to get each user one by one. But I don't know how to tell retrofit.
Hope I'm clear and
Thank you in advance.
----------- Solution :
I made my interface this way :
#FormUrlEncoded
#POST(AppConstants.ROUTE_USER_GROUP)
Call<Map<String,User>> getUsers( #Field("ids") List<String> param, #QueryMap Map<String,String> options);
and I simply gave my ArrayList of ids. Thank you very much
Gson is able to deal with JSON objects with variable keys like the one you posted. What you have to do, in this case, is to declare a Map<String, ModelClass>, where ModelClass is the content of the JSONObject you want to represent

Categories

Resources