How to insert Json Object inside Json Array in Kotlin using gson - android

I am new in using gson. I have tried several times to insert a Json Object inside a Json Array in Kotlin. I was able to successfully create the Json Array with Json Object and save it to internal storage. However, I wasn't able to insert Json Object inside it with this code. Any suggestions on how I would be able to achieve this? I've tried to get the file from internal storage and I couldn't fromJson it so I'm not sure if this idea would work. The data in the array are all strings. Here is my code:
fun save(){
var gson = Gson()
val filename = "name"
val file = context?.getFileStreamPath(filename)
if(file == null || !file.exists()){
val array= ArrayList<arraylist>()
array.add(arraylist("1","2","3"))
var json:String=gson.toJson(array).replace("\\n", "\n")
context?.openFileOutput(filename, Context.MODE_PRIVATE).use {
it?.write(json.toByteArray())
}
}
else{
val file = File(context?.filesDir, filename)
val contents = file.readText()
val gson = GsonBuilder().create()
val content = gson.fromJson(contents, arraylist::class.java)
content.add(arraylist("1","2","3"))
var json:String=gson.toJson(content).replace("\\n", "\n")
}
}

I finally fixed this by reading it then saving it to internal storage. This is inside the else{} statement:
val file1 = File(context?.filesDir, filename)
val contents = file1.readText()
val array = gson.fromJson(contents, Array<arraylist>::class.java)
val arrayList = ArrayList(array.toMutableList())
arrayList.add(devices("Finally","Works","Wow"))
val json: String = gson.toJson(arrayList).replace("\\n", "\n")
context?.openFileOutput(filename, Context.MODE_PRIVATE).use {
it?.write(json.toByteArray())
}

Related

How to read data from JSON file on the resources directory?

How to read data from JSON file on the resources directory?
I need to read a json file on the resources directory, convert it to a data class ("User")
I'm trying to adapt the following code
private fun getJSONFromAssets(): String? {
var json: String? = null
val charset: Charset = Charsets.UTF_8
try {
val myUsersJsonFile = assets.open("users.json")
val size = myUsersJsonFile.available()
val buffer = ByteArray(size)
myUsersJsonFile.read(buffer)
myUsersJsonFile.close()
json = String(buffer, charset)
} catch (ex: IOException) {
ex.printStackTrace()
return null
}
return json
}
but assets.open("users.json") is not recognized.
How is the best approach to read JSON files on the resources directory (mock data)?
You just need a minor change in your function...
private fun getJSONFromAssets(context: Context): String? {
...
val myUsersJsonFile = context.assets.open("users.json")
...
}
Assuming that your json file is at src/main/assets.
If you need to read a JSON file from the src/main/res/raw folder. You can use:
private fun getJSONFromAssets(context: Context): String? {
...
val myUsersJsonFile = context.resources.openRawResource(R.raw.users)
...
}
As you can see, you need a Context, so you can call from your activity.
getJSONFromAssets(this) // "this" is your activity (or another Context)

Gson toJson returning string of JSON instead of JSON Object

The Class that I'm using with toJson
class LoadUserDTO: Serializable {
#SerializedName("userGuid")
var userGuid: String? = null
#SerializedName("userToken")
var userToken: String? = null
constructor(userGuid: String, userToken: String) {
this.userGuid = userGuid
this.userToken = userToken
}
}
And the rest of the use:
val payload = LoadUserDTO(userGuid = user.guid!!, userToken = user.token!!)
val jsonPayload = Gson().toJson(payload)
this.socketService.socket.emit(EndpointsEnum.AppLoadUser, jsonPayload)
The jsonPayload should be a JSON Object. Instead, the entire thing is a String of what should be a JSON Object:
"{"userGuid":"...","userToken":"..."}"
When this is received by the server, it's not receiving a JSON Object as the Web UI or Swift App sends, but is instead just a String, not converted to a JSON Object.
try this,
var jsonString = """{"id":1,"description":"Test"}""";
var testModel = gson.fromJson(jsonString, TestModel::class.java)
Based on your requirement instead using Gson you may use String.format to achieve this by one line of code -
// val payload = LoadUserDTO(userGuid = user.guid!!, userToken = user.token!!)
// val jsonPayload = Gson().toJson(payload)
val jsonPayload = String.format("\"{\"userGuid\": \"%s\"," + "\"userToken\": \"%s\"" + "}\"",user.guid,user.token)
// Log.d("ZI",jsonPayload)
Output- example
"{"userGuid": "1234","userToken": "token000"}"
You may remove space after : while formatting string .
val jsonPayload = String.format("\"{\"userGuid\":\"%s\"," + "\"userToken\":\"%s\"" + "}\"",user.guid,user.token)
Output-
"{"userGuid":"1234","userToken":"token000"}"
I don't fully understand why yet, but this SO Question gave me the answer for it to work:
Send JSON data from in socket.io from android
val jsonPayload = Gson().toJson(payload)
val jsonObj = JSONObject(jsonPayload)
this.socketService.socket.emit(EndpointsEnum.AppLoadUser, jsonObj)
After making the jsonObj the server now has a properly formed JSON Object that it can work with.

JSONArray into Kotling Array/List and Setting value in spinner

I am performing a HTTP request from an API that gives me a JSON Array, I have been able to parse it but I am not able to convert it into a list or array in order to set it within the spinner. Here is what I have tried:
HTTP CALL:
private fun initiate() {
var product = 1
val httpAsync = "https://link_here"
.httpGet()
.responseString { request, response, result ->
when (result) {
is Result.Failure -> {
val ex = result.getException()
println(ex)
}
is Result.Success -> {
val data = result.get()
val json = JSONArray(data)
println(json)
nebulae = listOf(json)
}
}
}
httpAsync.join()
}
the response looks like this:
[{"_nebulae_id":"2","_ss_id":"1","_product_id":"2","product_type":"Dust"},{"_nebulae_id":"2","_ss_id":"3","_product_id":"1","product_type":"Star"}]
Here is the spinner code:
val spinnerProducts: Spinner = findViewById(R.id.spinnerProducts)
var adapter= ArrayAdapter(this,android.R.layout.simple_list_item_1,nebulae)
ArrayAdapter(
this,
android.R.layout.simple_spinner_item,
nebulae // insert list
).also { adapter ->
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
spinnerProducts.adapter = adapter
}
P.S I am new to Kotlin and it's been very long time since I used Java.
Firstly, nebulae = listOf(json) will not parse the list inside the json, will only put the whole json as an element of a list.
Create your data class for holding response:
data class Nebulae(
#SerializedName("_nebulae_id") val nebulae_id: String,
#SerializedName("_ss_id") val ss_id: String,
#SerializedName("_product_id") val product_id: String
#SerializedName("product_type") val product_type: String
)
If you want to use Gson, then convert your response like that:
val type = object : TypeToken<List<Nebulae>>() {}.type
val decodedResponse = Gson().fromJson<List<Nebulae>>(json, type)
If you want to use kotlinx.serialization, then convert your response as follows:
val decodedResponse = Json.decodeFromString<List<Nebulae>>(your_json_string)

Android Retrofit on Kotlin how i can add timestamp to response?

I have a simple Json class that handles retrofit perfectly.
But there is no timestamp in it.
I add my custom field which is not in json, but it is always null
//Custom field for timestamp
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
//My class for JSON respons
#Entity(tableName = "nal")
data class CurrencyItem(
#PrimaryKey(autoGenerate = true)
val id:Long,
#SerializedName("base_ccy")
var baseCcy: String,
#SerializedName("buy")
val buy: String,
#SerializedName("ccy")
val ccy: String,
#SerializedName("sale")
val sale: String,
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
)
Simplest solution add custom field in model for timestamp.
val timeStamp: String
Аnd when retrofit response come, rewrite this null field with timestamp, i use method SimpleDateFormat
// retrofit response
var res = resp.body()
// new list which i create and rewrite with timestamp and then return
var l = ArrayList<CurrencyItem>()
//read response list with json converted data
for (r in res.orEmpty()){
l.add(CurrencyItem(1 ,
r.baseCcy,
r.buy,
r.ccy,
r.sale,
SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())))
}
//return this new list with timestamp. I use repository pattern with livedata
response.value = l

How to store 2D array in android shared preference in kotlin?

I want to store 2D array using shared preference ?
Here I am trying to store 2D array in shared preference from one activity and after that i can load it in another activity using previously stored 2D array but i am not able to store 2D array in shared preference.
val _rMsg = intent.getStringArrayExtra(rKey)
val inflater = getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
val parent = _class11_
val _arData = arrayListOf<Array<String>>()
val sharedPreferences = getSharedPreferences("shared pref", Context.MODE_PRIVATE)
val gson = Gson()
val backJson = sharedPreferences.getString("task_li",null)
val type = TypeToken<ArrayList<>>() {}.type
_arData.add(gson.fromJson(backJson,type))
try {
_arData.add(_rMsg)
val edit = sharedPreferences.edit()
val json = gson.toJson(_arData)
edit.putString("task_li",json)
edit.apply()
for (i in _arData) {
val cardView = inflater.inflate(R.layout._preset_layout, null)
val mT = cardView.findViewById<TextView>(R.id._title__)
mT.text = i[0].toString()
parent.addView(cardView)
}
} catch (ex: Exception) {
}
We can use ObjectSerializer. [ https://github.com/apache/pig/blob/89c2e8e76c68d0d0abe6a36b4e08ddc56979796f/src/org/apache/pig/impl/util/ObjectSerializer.java ] this awesome class permit you to simple serialize and deserialize every kind of object, so you can simply save them as string into shared. You can store it like this :
val mArrayTest = arrayListOf<Array<String>>()
mArrayTest.add(arrayOf("1","3"))
mArrayTest.add(arrayOf("2","4"))
edit.putString("mArrayTest",ObjectSerializer.serialize(mArrayTest)).commit()
and get it like this :
val mTestStr = pref.getString("mArrayTest",null)
if (mTestStr != null) {
val mTestStr2 = ObjectSerializer.deserialize(mTestStr) as ArrayList<Array<String>>
Toast.makeText(this, mTestStr2[0][1].toString(), Toast.LENGTH_SHORT).show()
}

Categories

Resources