嵌套数组和 JSON 的问题

Posted

技术标签:

【中文标题】嵌套数组和 JSON 的问题【英文标题】:Troubles with nested array and JSON 【发布时间】:2020-03-17 07:53:37 【问题描述】:

您好)我是 android 开发新手。我的程序有问题。 这是我的模型:

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)

这就是我从 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

        

这是我的JSON 的链接。如果需要)

然后我正在做类似的事情:

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)

我需要获取确定项目的 ArrayList 并使用 bundle 将其数据放入片段中。 但是我在片段中有一个问题:

 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)

        

它从像 screen 这样的所有项目中放入了 singleChoiseAnswer 的所有值。请帮帮我)我知道这是一个简单的问题,但我真的不明白)

提前致谢) 附言S对不起我的英语)

【问题讨论】:

你能说出片段中的问题吗? @theanilpaudel 很可能问题出在我将值放入片段的循环中。我只需要放一个数组singleChoiceAnswer,但它把所有来自JSON的sinleCHoceArray,看屏幕 【参考方案1】:

首先,你需要将你的Json转换成Kotlin类,你可以使用GSON 将您的 json 转换为像这样的 kotlin 数据类

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)
        
    

要了解 Parcelable,请访问 link

然后当这完成后,像这样解析JSON

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


    





然后在适配器项目中点击

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

然后在片段中

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

【讨论】:

以上是关于嵌套数组和 JSON 的问题的主要内容,如果未能解决你的问题,请参考以下文章

如何访问和处理嵌套对象、数组或 JSON?

如何访问和处理嵌套对象、数组或 JSON?

如何访问和处理嵌套对象、数组或 JSON?

如何访问和处理嵌套对象、数组或 JSON?

使用 Alamofire 和 Swift 返回嵌套 JSON 数组中的值

JSON 可解码嵌套数组具有不同的格式和类型