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)