1

I'm having hard times trying to parse the following JSON and save it in a list.

{
  "statut": "Success",
  "rubrique": [
    {
      "rubrique": "Accueil",
      "position": "1"
    },
    {
      "rubrique": "Films",
      "position": "2"
    },
    {
      "rubrique": "Séries",
      "position": "3"
    },
    {
      "rubrique": "Sketchs",
      "position": "4"
    },
    {
      "rubrique": "Musique",
      "position": "5"
    }
  ]
}

I tried several methods then the below code worked,exept my list only contains one item: Musique

val queue = Volley.newRequestQueue(activity)
        val stringRequest = StringRequest(Request.Method.GET, endpoint,
            Response.Listener<String> { response ->
                val stringResponse = response.toString()
                val jsonObj = JSONObject(stringResponse)
                val jsonArray: JSONArray = jsonObj.getJSONArray("rubrique")

                for (i in 0 until jsonArray.length()) {
                    val innerBlock: JSONObject = jsonArray.getJSONObject(i)
                    val item: RubriqueItem = RubriqueItem()
                    item.position = innerBlock.getString("position")
                    item.rubrique = innerBlock.getString("rubrique")

                    categories?.add(item)
                }
                binding?.viewPagerMain?.adapter = BaseCategoriesFragmentPagerAdapter(
                    parentFragmentManager, categories)
                binding?.tabLayout?.setupWithViewPager(binding?.viewPagerMain)
            },
            Response.ErrorListener {error -> error.printStackTrace() })
        queue.add(stringRequest)

categories is ArrayList which I need to pass to the ViewPager's adapter. Tried to figure out a way to pass the index but I'm new to Kotlin can't figure out yet

Any hint is welcome

Lyra
  • 61
  • 1
  • 11

2 Answers2

2

You could use Gson lib for that.

First prepare the data class for the response.

ApiResponse.kt:

data class Rubrique(
    val rubrique: String,
    val position: String
)

data class ApiResponse(
    val statut: String,
    val rubrique: List<Rubrique>
)

And then to parse the response you just need one line:

val responseObject = Gson().fromJson(stringResponse, ApiResponse::class.java)

responseObject will have all the info. And the list in responseObject.rubrique.

Your code would be after this:

val stringRequest = StringRequest(Request.Method.GET, endpoint,
    Response.Listener<String> { response ->
        val responseObject = Gson().fromJson(response.toString(), ApiResponse::class.java)
        binding?.viewPagerMain?.adapter = BaseCategoriesFragmentPagerAdapter(
            parentFragmentManager, responseObject.rubrique)
        binding?.tabLayout?.setupWithViewPager(binding?.viewPagerMain)
    },
    Response.ErrorListener {error -> error.printStackTrace() })
queue.add(stringRequest)
jeprubio
  • 17,312
  • 5
  • 45
  • 56
  • Thanks for this solution,but what is json in private var categories: ArrayList? = ArrayList() ? – Lyra May 21 '20 at 11:11
  • After this line you have all the list in `responseObject.rubrique` as `List` and each element will have the `rubrique` and `position` attributes – jeprubio May 21 '20 at 11:18
  • 1
    Thanks, will definitely use this method. Thank you – Lyra May 21 '20 at 11:20
  • I think kotlinx.serialization is way better for this purpose as it does not use reflection and hence alot faster. I'd recommended that over Gson for less boilerplate and higher performance @Lyra – Animesh Sahu May 21 '20 at 12:10
  • Would you mind to provide an example that I can follow? – Lyra May 21 '20 at 14:24
  • I've updated the sample. I don't use the kotlinx.serialization yet because I'm waiting until it leaves the experimental phase. They are quite similar in performance and syntax so changing from one to the other should be easy. – jeprubio May 21 '20 at 14:48
  • @jeprubio Well, I tried the last snipet: responseObject.rubrique is arising a type mismatch, it's a ```(Mutable) List!``` while ```ArrayList``` is expected. So I tried to cast ```responseObject.rubrique``` to ```ArrayList?``` – Lyra May 21 '20 at 18:02
  • Well, yes and no, best practices is to program to interfaces and not specific implementations, it's one of the basics of object oriented programming so you should accept in the adapter List as a parameter instead of ListArray, but I'm just saying, feel free to follow this practice or not – jeprubio May 21 '20 at 18:25
1

Where exactly did you initialize "categories"?

I see 2 possible problems here: 1 -> categories only contains your last data. (you could see if it is that adding:

Log.d("VolleyRequestResult", categories.toString()

just before

binding?.viewPagerMain?.adapter = BaseCategoriesFragmentPagerAdapter(
                    parentFragmentManager, categories)

2 -> your BaseCategoriesFragmentPagerAdapter only display the last data (you should share this code so we can better understand what is happening)

benjiii
  • 413
  • 3
  • 9
  • like this: private var categories: ArrayList? = ArrayList(). The adapter is fine, its simply assign each item to tabs and get item count from categories size – Lyra May 21 '20 at 11:07