How to convert unstructured JSON to POJO using Moshi and Retrofit - android

I came across one issue with some of the response we getting is not straight to parse and convert it to POJO. The format of response I am getting is as below
[
"list",
[
{
"#type": "com.exampe.model.ModelName",
"number": 1,
"name": "Test Name",
"url": "/test/url/",
"type": "f"
}
]
]
I want to ignore that "list" and parse a POJO in List of object ModelName. I am using Retrofit and Moshi Convertor but I am not sure how I can achieve this. Is there any way that I can intercept the response before it passed to Moshi Convertor or any different approach that I can go for.
Retrofit Snippet
private fun getRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl(BuildConfig.API_URL)
.addConverterFactory(MoshiConverterFactory.create())
.client(getHTTPClient())
.build()
}

Retrofit offers custom converters (see official documentation),moshi also should offer something similar.
I do not have experience in using moshi, but I have checked documentation and source code - it looks it is possible.
Moshi offers custom adapters which should do things you need. Take a look on PolymorphicJsonAdapterFactory, it has methods fromJson() and toJson() which allows you manually parse json elements in which way you like.
Even more. PolymorphicJsonAdapterFactory looks as an option you need for this.
A JsonAdapter factory for objects that include type information in
the JSON. When decoding JSON. Moshi uses this type information to
determine which class to decode to. When encoding Moshi uses. the
object’s class to determine what type information to include.

Related

How to parse YAML response body to POJO in Retrofit library?

I have a problem with handling responses in YAML format in Retrofit. Until now I only handled the response body in JSON format or plain text. For these types, I always have prepared converters like gson, jackson for JSON and scalars for plain text. I found repository with all converters: retrofit-convertes.
In the documentation is a short mention that I need to create my own converter for this type.
If you need to communicate with an API that uses a content-format that Retrofit does not support out of the box (e.g. YAML, txt, custom format) or you wish to use a different library to implement an existing format, you can easily create your own converter. Create a class that extends the Converter.Factory class and pass in an instance when building your adapter.
Sadly, I don't see any tutorial on how to create such a converter. Is there any documentation explaining how to do this or is there any other option to handle such a case?
In your case you can use Jackon with yaml data formats.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("<your base url>")
.addConverterFactory(JacksonConverterFactory.create(new ObjectMapper(new YAMLFactory())))
.build();
For more informating check the following links:
https://github.com/square/retrofit/tree/master/retrofit-converters/jackson
https://github.com/FasterXML/jackson-dataformats-text/tree/master/yaml

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 - Convert Json response to easily store data with Room

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.

Retrofit and Generics and Inconsistent API data

From Retrofit's documentation:
RESPONSE OBJECT TYPE
HTTP responses are automatically converted to a specified type using the RestAdapter's converter which defaults to JSON. The desired type is declared as the method return type or using the Callback or Observable.
#GET("/users/list")
List<User> userList();
Retrofit will automatically convert a returned response (JSON, XML, etc) into the desired object that is specified by the method.
In the documentation's case, it will return a List of User objects.
How can one interface retrofit with a badly designed API that returns a list of different typed objects.
The psudocode will look something like:
#GET("/users/list")
List<User|Pet> userList();
Edit: The API returns a mix of the two types together. There are no flags or switches to change that.
Example /users/list:
{
"data": [
{
"animal": "dog",
"speak": "woof"
},
{
"username": "Bob",
"age": 30
}
]
}

Deserializing array response with a wrapper

I'm attempting to use Retrofit for communicating with an API that returns JSON arrays with a wrapper object. That is, a request to /apples.json would return the following:
{
apples: [ {apple1}, {apple2}, ... ]
}
Retrofit appears to expect the response to be of the form:
[ {apple1}, {apple2}, ...]
Is there a simple configuration option to handle this without having to write a custom Gson deserializer?

Categories

Resources