I need to create variables that should be named exactly like its API response to save data inside them. So that's why I have to create variables like this:
val 50: String
val 100: String
But as you know I can't do this so how can I create variables which names only contain digits?
If you use Gson library to convert Json api to kotlin Data class, add the same #SerializedName("key_api") annotation.
import com.google.gson.annotations.SerializedName
data class YourResponse {
#SerializedName("50")
val firstVariableName: String? = null,
#SerializedName("100")
val secondVariableName: String? = null
}
With this annotation, Gson will map the key of that Json with your variable name.
You do it by wrapping with `
// define
val `50`: String
val `100`: String
// access
`50` = "123"
`100` = "456"
println("${`50`}${`100`}")
If you use Retrofit with Gson, you should use #SerializedName Check this out
Related
I have this model that I would like to parse from JSON:
class CFInsertedValuesStructure {
#SerializedName("id")
val id : Int? = null
#SerializedName("value")
val value : List<String> = listOf();
#SerializedName("field_id")
val field_id : String? = null
}
There is a problem with the parameter "value" because it isn't always an array of String, sometimes it could be just a String type.
So when happens I would like to recognise it and create an array of just one String.
depending on what library you use the json parsing it may require a custom parsing type e.g. for kotlinx.serialization you might need to do something like a custom serializer
https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/serializers.md#specifying-serializer-on-a-property
better still : tell you server-side developer it should always be an array!
from an API call i get as response a body with this structure
open class BaseResponseEntity {
#SerializedName("result")
val result: ResultEnum = ResultEnum.NONE
#SerializedName("errorCode")
val errorCode: String = ""
#SerializedName("errorMessage")
val errorMessage: String = ""
#SerializedName("successMessage")
val successMessage: String = ""
#SerializedName("value")
val code: LastPaymentCodeModel?
}
where the field "value" can be three types: null, String or LastPaymentCodeModel. How can i get this?
I managed to put a ? so that both null and LastPaymentCodeModel are handled, but i don't know how to handle the String type too.
I think the best approach would probably be to use type Any? for code.
Then you should write a custom GSon serializer/deserilizer (JsonDeserializer<BaseResponseEntity>) for the BaseResponseEntity object.
In this Json deserializer, you would need to check the type of value (e.g is it a string or a data structure) and decode it to the correct object type.
Alternative, to avoid the use of Any?, you could leave the model exactly as you have it. You will still need to write a custom JsonDeserializer, however if value is a string then it would still create a LastPaymentCodeModel, using the string value as one of it's properties.
I am working on android application and want to manage null value that is comes from API.
I did not found the best solution.
I also try these methods
1. While generating getter in model class i give a conditional statement in getter like
if(value == null){
value = ""
}
but this is not a right way because of i have to write this code for each and every getter in whole application.
2. replace the string from 'null' to "" before JSON parsing.
this is replace all type of value (int/float etc) in to blank string that is invalid.
You can use JsonDeserializer to create your Gson.
You can create model class like this
class ExampleModel {
#SerializedName("id")
#Expose
val id: Int? = null
#SerializedName("category")
#Expose
val category: String? = null
}
This class will be able to handle null value and data as well.
I'm using Jackson 2.9.2 and Retrofit 2.1.0 for some POST operation with a JSONArray as HTML-Header parameter.
The API defines a value which is aId. No matter what I try, my JSON property is always converted to lowercase (aid).
I tested my same code with abId, and it works... Anyone a clue, where my configuration is wrong or which convention(?) is against this property name?
//ObjectMapper initialization
ObjectMapper().disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
//the data class
import com.fasterxml.jackson.annotation.JsonProperty
data class MyClass(
#JsonProperty
val aId: String? = null, //<-- not working
#JsonProperty
val abId: String? = null //working!
)
//Retrofit call
import retrofit2.http.Body
#POST("log")
fun sendLog(#Body logs: List<MyClass>): Call<MyCall>
//JSON Result in HTML Header
[{
"aid":"some_value", //should be "aId"
"abId":"some_value" //is correct
}]
I tried with following Annotations:
#SerializedName("aId")
#JsonProperty("aId")
#JsonRawValue
#JsonAlias
Try this #get:JsonProperty("aId")
See Michael Ziober' posted link for answer Usage of Jackson #JsonProperty annotation for kotlin data classes
Described issue is a result of Jackson's default bahaviour to not scan private fields. This behaviour can be change with #JsonAutoDetect
#JsonAutoDetect(fieldVisibility = Visibility.ANY)
data class MyClass(
#JsonProperty
val aId: String? = null,
#JsonProperty
val abId: String? = null
)
I use this class to store data
public class Item(var name:String,
var description:String?=null){
}
And use it in ArrayList
public var itemList = ArrayList<Item>()
Use this code to serialize the object
val gs=Gson()
val itemListJsonString = gs.toJson(itemList)
And deserialize
itemList = gs.fromJson<ArrayList<Item>>(itemListJsonString, ArrayList::class.java)
But this method will give me LinkedTreeMap, not Item, I cannot cast LinkedTreeMap to Item
What is correct way to deserialize to json in Kotlin?
Try this code for deserialize list
val gson = Gson()
val itemType = object : TypeToken<List<Item>>() {}.type
itemList = gson.fromJson<List<Item>>(itemListJsonString, itemType)
You can define a inline reified extension function like:
internal inline fun <reified T> Gson.fromJson(json: String) =
fromJson<T>(json, object : TypeToken<T>() {}.type)
And use it like:
val itemList: List<Item> = gson.fromJson(itemListJsonString)
By default, types are erased at runtime, so Gson cannot know which kind of List it has to deserialize. However, when you declare the type as reified you preserve it at runtime. So now Gson has enough information to deserialize the List (or any other generic Object).
In my code I just use:
import com.google.gson.Gson
Gson().fromJson(string_var, Array<Item>::class.java).toList() as ArrayList<Type>
I give here a complete example.
First the type and the list array:
class Item(var name:String,
var description:String?=null)
var itemList = ArrayList<Item>()
The main code:
itemList.add( Item("Ball","round stuff"))
itemList.add(Item("Box","parallelepiped stuff"))
val striJSON = Gson().toJson(itemList) // To JSON
val backList = Gson().fromJson( // Back to another variable
striJSON, Array<Item>::class.java).toList() as ArrayList<Item>
val striJSONBack = Gson().toJson(backList) // To JSON again
if (striJSON==striJSONBack) println("***ok***")
The exit:
***OK***
Instead of the accepted answer (that works but creates an object to get its type), you could just do:
val gson = Gson()
itemList = gson.fromJson(itemListJsonString, Array<Item>::class.java)
There "Array" represents a Java array when targeting the JVM platform. That's not an ArrayList but you can access the items (that's usually all is needed after parsing JSON).
If you still need to manipulate the list you could easily convert it to mutable by doing:
itemsList.toMutableList()