Search code examples
androidlistkotlinany

Convert existing List into a json/text file so moving forward read the data from that file to generate the List


How do I change this List<Any> into text/json file and then read it? As this FAQ question and answer will be hardcoded, so, I do not want it to be set directly inside my fragment. I'm planning to put the info into assets file, then read it from there to generate the List

My List<Any>

val list: List<Any> = arrayListOf(
        "General",
        FAQ(faqQuestion = "ABC?", faqAnswer = "QWERTY", expanded = false),
        FAQ(faqQuestion = "DEF?", faqAnswer = "ZXCVBN", expanded = false),
        "Troubleshooting",
        FAQ(faqQuestion = "ZXC?", faqAnswer = "POIUYT", expanded = false)
)

I do not know how to convert this into JSON or text file and successfully export it into this List.

What I tried so far are:

faq.json

[
  "General",
  {
    "expanded":false,
    "faqQuestion":"ABC?",
    "faqAnswer":"QWERTY"
  },
  {
    "expanded":false,
    "faqQuestion":"DEF?",
    "faqAnswer":"ZXCVBN"
  }
]

Text file faq.txt

"General",
FAQ(faqQuestion = "ABC?", faqAnswer = "QWERTY", expanded = false),
FAQ(faqQuestion = "DEF?", faqAnswer = "ZXCVBN", expanded = false),
"Troubleshooting",
FAQ(faqQuestion = "ZXC?", faqAnswer = "POIUYT", expanded = false)

Code to get from assets: Text

fun loadFromAsset(fileName: String, context: Context): Any? {
    val any: Any
    try {
        val ins = context.getAssets().open(fileName)
        val size = ins.available()
        val buffer = ByteArray(size)
        ins.read(buffer)
        ins.close()
        any = String(buffer, Charset.forName("UTF-8"))
    } catch (ex: IOException) {
        ex.printStackTrace()
        return null
    }

    return any
}

var list: List<Any>?
loadFromAsset("faq.txt", requireContext())?.let {
    list = arrayListOf(it)
}

JSON

fun loadFromAsset(fileName: String, context: Context): String? {
    var json: String? = null
    try {
        val ins = context.getAssets().open(filename)
        val size = ins.available()
        val buffer = ByteArray(size)
        ins.read(buffer)
        ins.close()
        json = String(buffer, Charset.forName("UTF-8"))
    } catch (ex: IOException) {
        ex.printStackTrace()
        return null
    }

    return json
}

val list: List<Any> = Gson().fromJson(loadFromAsset("faq.json", requireContext()), Array<Any>::class.java).asList()

Both way cannot get as per the original List<Any>


Solution

  • If your json contains only String and FAQ elements

    val list: List<Any> = gson.fromJson(json, JsonArray::class.java).map {
        when (it) {
            is JsonPrimitive -> it.asString as Any
            else -> gson.fromJson(it, FAQ::class.java) as Any
        }
    }