Home > Mobile >  Android Kotlin Volley jsonObjectRequest always invoking VolleyError
Android Kotlin Volley jsonObjectRequest always invoking VolleyError

Time:06-06

Im trying to use Volley to get a JSON object from an API and then display it in a recyclerview using the MVVM Android.

Using Volley jsonObjectRequest Get request in the ModelView (SchoolViewModel) to get my data (JSON Object) parsed through Gson and pass it into my LiveData, then set up an observer in my View (MainFragment) to observe that data and keep updating it in the recycler.

Now the issue is that Volley is only invoking Error, "com.android.volley.ParseError: org.json.JSONException: Value [{"dbn":"02M260","school_name":"Clinton School.... "

I am not sure what is causing the parsing error, as it seems to be retrieving the JSON object as seen following by the error.

Any ideas why it's always jumping to VolleyError?

My View:

class MainFragment : Fragment() {

private lateinit var schoolViewModel: SchoolViewModel
private lateinit var linearLayoutManager: LinearLayoutManager
private var mainRecyclerAdapter: MainRecyclerAdapter = MainRecyclerAdapter()
//private var list: MutableList<MutableLiveData<SchoolsData>> = mutableListOf()
private var schoolsData = MutableLiveData<List<SchoolsData>>()
val API_Schools: String = "https://data.cityofnewyork.us/resource/s3k6-pzi2.json"
val API_SAT: String = "https://data.cityofnewyork.us/resource/f9bf-2cp4.json"

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)


}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) : View? {
    // Inflate the layout for this fragment
    val binding = FragmentMainBinding.inflate(layoutInflater)
    schoolViewModel = ViewModelProvider(this).get(SchoolViewModel::class.java)
    linearLayoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL,false)

    context?.let { schoolViewModel.getData(it) }

    schoolViewModel._schoolsData.observe(viewLifecycleOwner, Observer{
        mainRecyclerAdapter.setData(it)
    } )

    binding.recyclerMain.apply {
        layoutManager = linearLayoutManager
        adapter = mainRecyclerAdapter
    }

return  binding.root
}


 }

ViewModel

class SchoolViewModel: ViewModel() {

private var schoolsData = MutableLiveData<List<SchoolsData>>()
val _schoolsData: LiveData<List<SchoolsData>> = schoolsData

private var satData = MutableLiveData<SATData>()
val _satData: LiveData<SATData> = satData

lateinit var jsonObjectRequest: JsonObjectRequest

val API_Schools: String = "https://data.cityofnewyork.us/resource/s3k6-pzi2.json"
val API_SAT: String = "https://data.cityofnewyork.us/resource/f9bf-2cp4.json"

fun getData(context: Context) {

    val requestQueue: RequestQueue = Volley.newRequestQueue(context.applicationContext)

    jsonObjectRequest = JsonObjectRequest(Request.Method.GET,API_Schools, null,
        {

           try {
               val gson = Gson()
               schoolsData = gson.fromJson(
                   it.toString(),
                   MutableLiveData<List<SchoolsData>>()::class.java
               )
               Log.e("RECEIVED", schoolsData.toString())

            }catch (e: JSONException){
                Log.e("JSONException", e.toString())
            }

        }, {

        Log.e("ERROR",it.toString())
        })
    requestQueue.add(jsonObjectRequest)
 }


 }

Model

import com.google.gson.annotations.SerializedName

data class SchoolsData(

@SerializedName("dbn")
val id: String,
@SerializedName("school_name")
val school_name: String,
@SerializedName("total_students")
val students_num: Int,
@SerializedName("graduation_rate")
val graduation_rate: Float,
@SerializedName("primary_address_line_1")
val street: String,
@SerializedName("city")
val city: String


)

CodePudding user response:

The JSON you are fetching is a JSONArray [{},{}] not a JSONObject, so you need to use JsonArrayRequest instead of JsonObjectRequest. Once you make that change, the volley error will go away, but you also need to update the parsing code - you should deserialize it to a List<SchoolsData>, not a MutableLiveData, like this:

val gson = Gson()
val listType = object : TypeToken<List<SchoolsData>>() {}.type
val schoolList = gson.fromJson<List<SchoolsData>>(
    it.toString(),
    listType
)
schoolsData.postValue(schoolList)
  • Related