Converting a HashMap using moshi - android

I'm trying to convert a HashMap of elements into a JSON string. I'm using the method used in this link.
val elementsNew: HashMap<String, Element> = HashMap(elements)
val type = Types.newParameterizedType(Map::class.java, String::class.java, Element::class.java)
var json: String = builder.adapter(type).toJson(elementsNew)
But this gives the following error
Error:(236, 40) Type inference failed: Not enough information to infer
parameter T in fun adapter(p0: Type!): JsonAdapter!
Please specify it explicitly.
Can any one tell me where's the fault? Is it because of Kotlin?

Looking at the signature of the adapter() method, it can't infer its type parameter from the argument:
public <T> JsonAdapter<T> adapter(Type type)
Hence you have to provide the type explicitly:
var json = builder.adapter<Map<String, Element>>(type).toJson(elementsNew)
or alternatively:
val adapter: JsonAdapter<Map<String, Element>> = builder.adapter(type)
var json = adapter.toJson(elementsNew)

Related

Correct way to parse eterogeneous arrays of data

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!

Converting an JSON string to Gson object

I have an JSONObject which is creating in the following way.
For a special reason, I have to convert it to Gson in this way, as i can modify only extractDataToString() method. But I do not get proper value after conversion.
fun createJsonString() {
val headerJson = JSONObject()
headerJson.put("typ1", "value1")
headerJson.put("typ2", "value2")
extractData(headerJson.toString())
}
fun extractDataToString(jsonString: String) {
val headerJson = Gson().fromJson(jsonString, JsonObject::class.java)
val resultType1 = headerJson.remove("typ1")?.toString() // Here, resultType1 becomes
"value1", but it should be
value1 that is extra qutomation
mark is being added.
}
Why extra quotation mark is being added? Can anyone please help? I am a newbie.
Call
.getAsString()
Instead of
toString()
at the end
ref : docs

Multi type object in kotlin

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.

How to parse a JSON string into a JSONObject in Kotlin?

I'm really new in programming, and recently started a project in Kotlin with Android Studio.
So, I have a problem with a JSON object. I get data from an BroadcastReceiver object, a String to be more specific, with the next format:
{"s1":1}
This, is a simple string. So I took in a function call toJson and I do this.
private fun toJson(data:String): JSONObject {
var newData: String = data.replace("\"","")
newData = newData.replace("{","")
newData = newData.replace("}","")
val newObject = newData.split(":")
val name = newObject[0]
val value = newObject[1]
val rootObject = JSONObject()
rootObject.put(name,value)
return rootObject
}
Im doing this the right way?, how can I improve my code?
Thanks for your help, and sorry for my english!
Welcome to StackOverflow!
In 2019 no-one is really parsing JSON manually. It's much easier to use Gson library. It takes as an input your object and spits out JSON string and vice-versa.
Example:
data class MyClass(#SerializedName("s1") val s1: Int)
val myClass: MyClass = Gson().fromJson(data, MyClass::class.java)
val outputJson: String = Gson().toJson(myClass)
This way you're not working with JSON string directly but rather with Kotlin object which is type-safe and more convenient.
Look at the docs. It's pretty big and easy to understand
Here is some tutorials:
https://www.youtube.com/watch?v=f-kcvxYZrB4
http://www.studytrails.com/java/json/java-google-json-introduction/
https://www.tutorialspoint.com/gson/index.htm
UPDATE: If you really want to use JSONObject then use its constructor with a string parameter which parses your JSON string automatically.
val jsonObject = JSONObject(data)
Best way is using kotlinx.serialization. turn a Kotlin object into its JSON representation and back marking its class with the #Serializable annotation, and using the provided encodeToString and decodeFromString<T> extension functions on the Json object:
import kotlinx.serialization.*
import kotlinx.serialization.json.*
​
#Serializable
data class User(val name: String, val yearOfBirth: Int)
​
// Serialization (Kotlin object to JSON string)
​
val data = User("Louis", 1901)
val string = Json.encodeToString(data)
println(string) // {"name":"Louis","yearOfBirth":1901}
​
// Deserialization (JSON string to Kotlin object)
​
val obj = Json.decodeFromString<User>(string)
println(obj) // User(name=Louis, yearOfBirth=1901)
Further examples: https://blog.jetbrains.com/kotlin/2020/10/kotlinx-serialization-1-0-released/
I am adding 3 templates here for Kotlin Developers, It will solve json converting & parsing problems.
//Json Array template
{
"json_id": "12.4",
"json_name": "name of the array",
"json_image": "https://image_path",
"json_description": "Description of the Json Array"
}
Kotlin Model class
data class JsonDataParser(
#SerializedName("json_id") val id: Long,
#SerializedName("json_name") val name: String,
#SerializedName("json_image") val image: String,
#SerializedName("json_description") val description: String
)
Converting to Json String from the Model Class
val gson = Gson()
val json = gson.toJson(jsonDataParser)
Parsing from Json file/Strong
val json = getJson()
val topic = gson.fromJson(json, JsonDataParser::class.java)

How to use gson deserialize to ArrayList in Kotlin

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()

Categories

Resources