How can I take array out of double quotes - android

Suppose if I've a string as
"[{"key1": value1}, {"key2": value2}, and so on...]"
is there a way to convert it into array:
[{"key1": value1}, {"key2": value2}, and so on...]
Actually I've to post a JSON request in my android app which should be in the following format:
{
"user_id": "5665",
"restaurant_id": "5",
"total_cost": "660",
"food":[
{"food_item_id": "50"},
{"food_item_id": "51"}
]
}
As in the above code, I've to use the array for food key which is stuck in string which I get using the following code:
val gson = Gson()
val menuIds = gson.toJson(listOfMenuIds)

You can create a dataclass for food_items to represent a item in the "food" array.
Then create another dataclass which has "user", "restaurant_id", ... so on... as members, including a member var foods: List
Then pass the second class to the Gson converter

Related

How to get field names as an array from json in Kotlin

I am parsing the below sample json using retrofit in android:
{
"success": true,
"timestamp": 1664080564,
"base": "EUR",
"date": "2022-09-25",
"rates": {
"AED": 3.559105,
"AFN": 86.151217,
"ALL": 116.321643,
"AMD": 404.265711
}
}
As you can see there is no array in this json data, but I want the values of rates as a list or a map so that I can get "AED, AFN, ALL, AMD" as an array too. How can i achieve that using retrofit?
You can define rates as a Map<String, Double> in your data class and Retrofit will automatically parse the rates in form of a Map.
data class MyModel(
val success: Boolean,
val timestamp: Long,
val base: String,
val date: String,
val rates: Map<String, Double>
)
so that I can get "AED, AFN, ALL, AMD" as an array too.
For this you can simply use rates.keys to get all the keys.

Consuming polymorphic json "data: { put_anything_here }" with Gson & Retrofit

I'm not sure if polymorphic is the right term to use so my apologies.
I'm working with the following API:
Request body:
{
"user_id": "user_id",
"command": "submit_document",
}
Response:
{
"result": "success",
"code": 200,
"status": "ok",
"screen": "documents_rejected", // This is unique for different `data`
"next_screen": "",
"message": "Successful",
"data": {
// `data` is always a json object with known fields and parameters
}
}
I have data classes ready for different types of data responses like:
data class PhoneData(
#SerializedName("phone_number")
val phoneNumber: String? = null,
#SerializedName("phone_status")
val phoneStatus: String? = null
)
for "screen": "phone" and the following for another screen:
data class Data(
val deepLink: String? = null
)
The problem is, at the start, I have to make the following request to retrieve the current screen:
{
"user_id": "user_id",
"command": "get_current_screen",
}
which returns a similar response as above:
{
"result": "success",
"code": 200,
"status": "ok",
"screen": "main_screen", // Different types of screen types are known.
"next_screen": "",
"message": "Successful",
"data": {
// `data` is always a json object but the object could contain anything depending on the `screen` type.
}
}
but the data field could contain anything depending on the screen
data class SplashScreenData(
// How do I make this data class combine all other data classes? One ugly approach is to add all the fields from different `data` classes here and use this one only.
)
I found about the RuntimeTypeAdapterFactory for polymorphic cases but am not sure how to make it work when there's no "type" like field within the data object (screen is unique but it's outside the data object).
It would be very helpful if someone has a solution or could point me in a direction.
val frameTextReceived: String = frame.readText()
val jsonObject = JsonParser.parseString(frameTextReceived).asJsonObject
val type = when (jsonObject.get("type").asString) {
TYPE_JOIN_ROOM -> JoinRoom::class.java
TYPE_GAME_MOVE -> GameMove::class.java
TYPE_DISCONNECT_REQUEST -> DisconnectRequest::class.java
else -> BaseModel::class.java
}
val payload = gson.fromJson(frameTextReceived, type)
This is my solution, here I have type parameter by which I can know in which class I have to deserialize the object but in your case you have screen parameter, you can use this.

Send a Json which is like key:{key:value,key:[]} with Volley

I am new to using Volley and parsing complex Json.
I have Json like:
"timings": {
"summary": "Mon-Fri 9am-6pm",
"detail": [
"Mon 9am-6pm",
"Tue 9am-6pm",
"Wed 9am-6pm",
"Thu 9am-6pm",
"Fri 9am-6pm"
]
}
I am not sure how to send it. I have tried to search for solutions but no luck.
Some help will be really helpful.
I suggest to use Gson library.
And with Gson create class with name of Timings and contain 2 variables .
data class Timings ( val summery: String , val details : List<String>)
val gson: Gson()
time = gson.fromJson(jsonString,Timings::class.java)
Other way is use Json Object and json array to parse it manually

Moshi Custom Adapter isn't being called

TL;DR:
My questions are:
1 - How can I make an Adapter for the "timestamp": 1515375392.225 to ZonedDateTime.
2 - How can I register the List<Report> adapter in the moshi object Builder if I need the moshi object to get this adapter, according to the documentation?
My JSON string has the following structure:
[
{
"id": 0,
"location": {
"latitude": -22.967049,
"longitude": -43.19096
},
"timestamp": 1515375392.225
},
{
"id": 0,
"location": {
"latitude": -22.965845,
"longitude": -43.191102
},
"timestamp": 1515375392.225
},
.......
}]
The timestamp is an automatic conversion made by the Jackson JavaTimeModule, it converts a ZonedDateTime to a timestamp String in the form of a decimal number representing the seconds and nanoseconds from an Instant.
In order to parse the JSON timestamp String, I made the following Moshi adapter:
public class ZonedDateTimeAdapter {
#FromJson ZonedDateTime fromJson(String timestamp) {
int decimalIndex = timestamp.indexOf('.');
long seconds = Long.parseLong(timestamp.substring(0, decimalIndex));
long nanoseconds = Long.parseLong(timestamp.substring(decimalIndex));
return Instant.ofEpochSecond(seconds, nanoseconds).atZone(ZoneId.systemDefault());
}
#ToJson String toJson(ZonedDateTime zonedDateTime) {
Instant instant = zonedDateTime.toInstant();
return instant.getEpochSecond() + "." + instant.getNano();
}
}
And then I register this adapter as:
Type type = Types.newParameterizedType(List.class, Report.class);
Moshi moshi = new Moshi.Builder().add(new ZonedDateTimeAdapter()).build();
JsonAdapter<List<Report>> reportAdapter = moshi.adapter(type);
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build();
The problem is, when I call my webservice using Retrofit, I get the following Exception:
com.squareup.moshi.JsonDataException: java.lang.NumberFormatException:
For input string: ".067000000" at $[0].timestamp
(keep in mind the nanoseconds .067000000 here won't be the same as the JSON example that I gave before, since they called the webservice at different times).
I tried to place a breakpoint on my ZonedDateTimeAdapter, but it's never being called. But it's influencing Moshi, because if I remove it from the Moshi.Builder, the error changes to:
Caused by: java.lang.IllegalArgumentException: Cannot serialize
abstract class org.threeten.bp.ZoneId
I also tried to change the ZonedDateTimeAdapter to deal with Double instead of String, but it just changes the error message to:
com.squareup.moshi.JsonDataException: java.lang.NumberFormatException:
For input string: ".515376840747E9" at $[0].timestamp
So, basically, I have a bunch of changing error messages and no idea what am I doing wrong. I followed the Moshi documentation on Custom Adapters and I don't know what else to do.
Your JSON adapter’s #ToJson methods is accepting a String but the timestamp is a number. Either change this to be a number (ie. double) or pass a JsonReader instead of a String and read the number out yourself. In this case you can call reader.nextString().

How to generate GSONFormat for a property that can either be an object or string?

I'm using GSON for parsing response from a Volley request and got stuck in creating a GSON format when the response has a property that can either be a string or an object or an array perhaps... e.g content
{
"data": {
"date_updated": "2016-12-21T03:55:29.955Z",
"date_created": "2016-12-21T03:55:29.955Z",
"content": "String here",
"content": {
"longitude": "",
"latitude": ""
},
"status": "PROC",
"_id": "5859fd31a93c7235575d62db"
}
}
My current process in creating a GSON model is:
Create a java class
Right click and select Generate > GSONFormat
Paste the object I'm trying to convert then use it in Volley.
I tried the above object but it doesn't proceed. I think it's because of same property name.
Thanks for your advice.
You can use GsonFormat, you can look this:
https://github.com/zzz40500/GsonFormat

Categories

Resources