Lemonyara
Lemonyara

Reputation: 53

Troubles with nested array and JSON

Hello) I'm new in Android dev. And I have a problem with my program. It's my model:

data class Test (val id: Int,
                 val numberQuestion: String,
                 val question: String,
                 val questionImageSrc: String,
                 val examination: Boolean,
                 val typeQuestion: String,
                 val singleChoiceAnswers: ArrayList<singleChoiceAnswer>,
                 val multipleChoiceAnswers: ArrayList<multipleChoiceAnswers>,
                 val inputAnswer: ArrayList<inputAnswer>)

data class multipleChoiceAnswers(val letter: String,
                                 val text: String,
                                 val correctAnswer: Boolean,
                                 val checked: Boolean)

data class singleChoiceAnswer(val letter: String,
                              val text: String,
                              val correctAnswer: Boolean,
                              val checked: Boolean)

data class inputAnswer(val correctAnswer: String,
                        val userAnswer: String)

It's how i get the data from JSON:

private fun jsonResult(jsonString: String?) {

            val jsonArray = JSONArray(jsonString)

            val list = ArrayList<Test>()
            val slist = ArrayList<singleChoiceAnswer>()
            val mlist = ArrayList<multipleChoiceAnswers>()
            val ilist = ArrayList<inputAnswer>()

            for (i in 0 until jsonArray.length()){
                val jsonObject = jsonArray.getJSONObject(i)
                val typeQuestion = jsonObject.getString("typeQuestion")

                val curentId = jsonObject.optInt("id")
                val curentNQ = jsonObject.optString("numberQuestion")
                val curentQ = jsonObject.optString("question")
                val curentQIS = jsonObject.optString("questionImageSrc")
                val curentEx = jsonObject.optBoolean("examination")


                if (typeQuestion.contains("multipleChoice")){
                    val multipleChoiceAnswers = jsonObject.getJSONArray("multipleChoiceAnswers")

                    for (sc in 0 until multipleChoiceAnswers.length()){
                        val curentMCA = multipleChoiceAnswers.getJSONObject(sc)
                        val letter = curentMCA.optString("letter")
                        val text = curentMCA.optString("text")
                        val correctAnswer = curentMCA.optBoolean("correctAnswer")
                        val checked = curentMCA.optBoolean("checked")

                        mlist.add(multipleChoiceAnswers(letter, text, correctAnswer, checked))
                    }

                }
                if (typeQuestion.contains("singleChoice")){
                    val singleChoiceAnswer = jsonObject.getJSONArray("singleChoiceAnswers")

                    for (sc in 0 until singleChoiceAnswer.length()){
                        val curentSCA = singleChoiceAnswer.getJSONObject(sc)
                        val letter = curentSCA.optString("letter")
                        val text = curentSCA.optString("text")
                        val correctAnswer = curentSCA.optBoolean("correctAnswer")
                        val checked = curentSCA.optBoolean("checked")

                        slist.add(singleChoiceAnswer(letter, text, correctAnswer, checked))
                    }


                }
                if (typeQuestion.contains("input")){
                    val inputAnswer = jsonObject.getJSONArray("inputAnswer")

                    for (sc in 0 until inputAnswer.length()){
                        val curentIA = inputAnswer.getJSONObject(sc)
                        val correctAnswer = curentIA.optString("correctAnswer")
                        val userAnswer = curentIA.optString("userAnswer")

                        ilist.add(inputAnswer(correctAnswer,userAnswer))
                    }
                }


                list.add(Test(curentId, curentNQ, curentQ, curentQIS, curentEx, typeQuestion, slist, mlist, ilist))


            }

            val adapter = TestAdapter(list) { item ->
                testAdapterItemClick(item)
            }

            val recView = findViewById<RecyclerView>(R.id.testRecyclerView)
            recView.adapter = adapter

        }

Here is link to my JSON. If you need it)

Then i am doing something like that:

private fun testAdapterItemClick(item: Test) {

        val fT: FragmentTransaction = supportFragmentManager.beginTransaction()

        val frag1: Fragment1 = Fragment1()
        val frag2: Fragment2 = Fragment2()

        if (item.typeQuestion == "input") {
            val bundle = Bundle()
            bundle.putString("NUMBER_KEY", item.numberQuestion)
            bundle.putString("QUESTION_KEY", item.question)

            if(!item.questionImageSrc.isNullOrEmpty())
                bundle.putString("IMAGE_KEY", item.questionImageSrc)

            frag1.setArguments(bundle)
            fT.add(R.id.frameLayout, frag1)
        }

        if (item.typeQuestion == "singleChoice") {
            val bundle = Bundle()
            bundle.putString("NUMBER_KEY", item.numberQuestion)
            bundle.putString("QUESTION_KEY", item.question)

            val count = item.singleChoiceAnswers.size
            Toast.makeText(this, count.toString(), Toast.LENGTH_LONG).show()
          //  bundle.putInt("COUNT_KEY", count)


            for (i in 0 until count)
            {
                val curentSCA = item.singleChoiceAnswers[i]

                bundle.putString("letterSCA$i", curentSCA.letter)
                bundle.putString("textSCA$i", curentSCA.text)

            }
frag2.setArguments(bundle)

            fT.add(R.id.frameLayout, frag2)

I need to get ArrayList of the definite item and put it data in fragment using bundle. But I have a problem in fragment:

 public override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?): View? {

        val rootView = inflater.inflate(R.layout.fragment2, container, false)

        val questionNumber = rootView.findViewById(R.id.questionNumber) as TextView
        val questionText = rootView.findViewById(R.id.Question) as TextView
        val questionImage = rootView.findViewById(R.id.questionImage) as ImageView

        val qN : String = getArguments()?.getString("NUMBER_KEY").toString()
        val quest: String = getArguments()?.getString("QUESTION_KEY").toString()
        val qI: String = getArguments()?.getString("IMAGE_KEY").toString()

        questionNumber.text=qN
        questionText.text=quest
        Picasso.get().load(qI).into(questionImage)

        val radioGroup = rootView.findViewById(R.id.radioGroupSetectTest) as RadioGroup

        val count : Int = getArguments()!!.getInt("COUNT_KEY")

        val context = getContext()

        for (i in 0 until count)
        {
            val curentRB = RadioButton(context)
            val curLetter = getArguments()?.getString("letterSCA$i")
            val curText = getArguments()?.getString("textSCA$i")


            curentRB.setText(curLetter+" "+curText)
            radioGroup.addView(curentRB)

        }

It put the all values of singleChoiseAnswer from all items like this screen. Please, help me) I know that it is a simple problem but i realy dont understand)

Thanks in advance) P.S. SOrry for my English)

Upvotes: 0

Views: 37

Answers (1)

theanilpaudel
theanilpaudel

Reputation: 3488

First of all, you need to convert your Json into Kotlin classes, you can use GSON to convert your json to kotlin data classes like this

import android.os.Parcel
import android.os.Parcelable
import com.google.gson.annotations.SerializedName

data class QuestionResponse(

    @field:SerializedName("multipleChoiceAnswers")
    val multipleChoiceAnswers: List<MultipleChoiceAnswersItem?>? = null,

    @field:SerializedName("inputAnswer")
    val inputAnswer: List<InputAnswer?>? = null,

    @field:SerializedName("numberQuestion")
    val numberQuestion: String? = null,

    @field:SerializedName("question")
    val question: String? = null,

    @field:SerializedName("typeQuestion")
    val typeQuestion: String? = null,

    @field:SerializedName("examination")
    val examination: Boolean? = null,

    @field:SerializedName("id")
    val id: Int? = null,

    @field:SerializedName("singleChoiceAnswers")
    val singleChoiceAnswers: List<MultipleChoiceAnswersItem?>? = null,

    @field:SerializedName("questionImageSrc")
    val questionImageSrc: String? = null
) : Parcelable {
    constructor(parcel: Parcel) : this(
        parcel.createTypedArrayList(MultipleChoiceAnswersItem),
        parcel.createTypedArrayList(InputAnswer),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
        parcel.readValue(Int::class.java.classLoader) as? Int,
        parcel.createTypedArrayList(MultipleChoiceAnswersItem),
        parcel.readString()
    ) {
    }

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeTypedList(multipleChoiceAnswers)
        parcel.writeTypedList(inputAnswer)
        parcel.writeString(numberQuestion)
        parcel.writeString(question)
        parcel.writeString(typeQuestion)
        parcel.writeValue(examination)
        parcel.writeValue(id)
        parcel.writeTypedList(singleChoiceAnswers)
        parcel.writeString(questionImageSrc)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<QuestionResponse> {
        override fun createFromParcel(parcel: Parcel): QuestionResponse {
            return QuestionResponse(parcel)
        }

        override fun newArray(size: Int): Array<QuestionResponse?> {
            return arrayOfNulls(size)
        }
    }
}


import android.os.Parcel
import android.os.Parcelable
import com.google.gson.annotations.SerializedName

data class MultipleChoiceAnswersItem(

    @field:SerializedName("letter")
    val letter: String? = null,

    @field:SerializedName("checked")
    val checked: Boolean? = null,

    @field:SerializedName("text")
    val text: String? = null,

    @field:SerializedName("correctAnswer")
    val correctAnswer: Boolean? = null
) : Parcelable {
    constructor(parcel: Parcel) : this(
        parcel.readString(),
        parcel.readValue(Boolean::class.java.classLoader) as? Boolean,
        parcel.readString(),
        parcel.readValue(Boolean::class.java.classLoader) as? Boolean
    ) {
    }

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeString(letter)
        parcel.writeValue(checked)
        parcel.writeString(text)
        parcel.writeValue(correctAnswer)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<MultipleChoiceAnswersItem> {
        override fun createFromParcel(parcel: Parcel): MultipleChoiceAnswersItem {
            return MultipleChoiceAnswersItem(parcel)
        }

        override fun newArray(size: Int): Array<MultipleChoiceAnswersItem?> {
            return arrayOfNulls(size)
        }
    }
}



import android.os.Parcel
import android.os.Parcelable
import com.google.gson.annotations.SerializedName

data class InputAnswer(
    @field:SerializedName("correctAnswer")
    val correctAnswer: String? = null,

    @field:SerializedName("userAnswer")
    val userAnswer: String? = null) : Parcelable {
    constructor(parcel: Parcel) : this(
        parcel.readString(),
        parcel.readString()
    ) {
    }

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeString(correctAnswer)
        parcel.writeString(userAnswer)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<InputAnswer> {
        override fun createFromParcel(parcel: Parcel): InputAnswer {
            return InputAnswer(parcel)
        }

        override fun newArray(size: Int): Array<InputAnswer?> {
            return arrayOfNulls(size)
        }
    }
}

To know about Parcelable go to this link

Then when this is complete, parse the JSON like this

private fun jsonResult(jsonString: String?) {

    val jsonArray = JSONArray(jsonString)

    val list = ArrayList<QuestionResponse>()
    val slist = ArrayList<MultipleChoiceAnswersItem>()
    val mlist = ArrayList<MultipleChoiceAnswersItem>()
    val ilist = ArrayList<InputAnswer>()

    for (i in 0 until jsonArray.length()){
        val jsonObject = jsonArray.getJSONObject(i)
        val typeQuestion = jsonObject.getString("typeQuestion")

        val curentId = jsonObject.optInt("id")
        val curentNQ = jsonObject.optString("numberQuestion")
        val curentQ = jsonObject.optString("question")
        val curentQIS = jsonObject.optString("questionImageSrc")
        val curentEx = jsonObject.optBoolean("examination")



        if (typeQuestion.contains("multipleChoice")){
            val multipleChoiceAnswers = jsonObject.getJSONArray("multipleChoiceAnswers")

            for (sc in 0 until multipleChoiceAnswers.length()){



                val curentMCA = multipleChoiceAnswers.getJSONObject(sc)
                val letter = curentMCA.optString("letter")
                val text = curentMCA.optString("text")
                val correctAnswer = curentMCA.optBoolean("correctAnswer")
                val checked = curentMCA.optBoolean("checked")



                mlist.add(MultipleChoiceAnswersItem(letter,checked, text, correctAnswer))
            }

        }
        if (typeQuestion.contains("singleChoice")){
            val singleChoiceAnswer = jsonObject.getJSONArray("singleChoiceAnswers")

            for (sc in 0 until singleChoiceAnswer.length()){
                val curentSCA = singleChoiceAnswer.getJSONObject(sc)
                val letter = curentSCA.optString("letter")
                val text = curentSCA.optString("text")
                val correctAnswer = curentSCA.optBoolean("correctAnswer")
                val checked = curentSCA.optBoolean("checked")

                slist.add(MultipleChoiceAnswersItem(letter, checked,text, correctAnswer))
            }


        }
        if (typeQuestion.contains("input")){
            val inputAnswer = jsonObject.getJSONArray("inputAnswer")

            for (sc in 0 until inputAnswer.length()){
                val curentIA = inputAnswer.getJSONObject(sc)
                val correctAnswer = curentIA.optString("correctAnswer")
                val userAnswer = curentIA.optString("userAnswer")

                ilist.add(InputAnswer(correctAnswer,userAnswer))
            }
        }

        val questionResponse = QuestionResponse(mlist,ilist,curentNQ,curentQ,typeQuestion,curentEx,curentId,slist,curentQIS)

        //pass this questionResponse to your adapter


    }




}

Then in Adapter Item click

private fun testAdapterItemClick(item: Test) {

    val fT: FragmentTransaction = supportFragmentManager.beginTransaction()

    val frag1: Fragment1 = Fragment1()
    val frag2: Fragment2 = Fragment2()

    if (item.typeQuestion == "input") {
        val bundle = Bundle()
        bundle.putParcelable("input", item)

        frag1.setArguments(bundle)
        fT.add(R.id.frameLayout, frag1)
    }
    // do the same for the rest
}

Then in the Fragment

public override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?): View? {

    val rootView = inflater.inflate(R.layout.fragment2, container, false)

    val questionNumber = rootView.findViewById(R.id.questionNumber) as TextView
    val questionText = rootView.findViewById(R.id.Question) as TextView
    val questionImage = rootView.findViewById(R.id.questionImage) as ImageView

    val item = arguments.getParcelable("input")
    // val arraylist = arguments.getParcelableArrayList<YOUR_CLASS_TYPE>("key") //for arrays you can do it like this
    //then set it in the radiobutton like this item.getCurrentText and so on
}

Upvotes: 0

Related Questions