问题
I am making an API request which returns some array values. I need to serialize these array values so that I can assign them to their corresponding class attributes (which are String types).
Now I know how to use GSON to serialize and deserialize lists, but with Retrofit the mapping is done automatically. This means that if my attribute is of type String, the API call returns the error "Expected a String but received an Array instead". How do I get around this so that I can receive them as arrays without failure, and them store them as strings subsequently?
My API Response:
{
"utterances": [{
"langs": ["eng", "afr", "xho", "zul"],
"utts": [
"Have you been here before?",
"Was u al hier gewees?",
"Ingaba wakhe weza apha ngaphambili?",
"Ingabe uke weza lapha ngaphambilini?"
],
"responses": [
["Yes", "No"],
["Ja", "Nee"],
["Ewe", "Hayi"],
["Yebo", "Cha"]
]
},
{
"langs": ["eng", "afr", "xho", "zul"],
"utts": [
"How are you?",
"Hoe gaan dit met jou?",
"unjani?",
"unjani?"
],
"responses": [
["Good", "Bad"],
["Goed", "sleg"],
["ezilungileyo", "ezimbi"],
["kuhle", "kubi"]
]
}
]
}
My UtteranceResponse class:
class UtteranceResponse {
@SerializedName("status")
var status: String? = null
@SerializedName("count")
var count: Int = 0
@SerializedName("utterances")
var utterances: ArrayList<Utterance>? = null
}
My Utterance class:
class Utterance: SugarRecord {
@SerializedName ("langs")
var langs: String? = null
@SerializedName ("utts")
var utterances_text: String? = null
var utterances_tts: String? = null
@SerializedName ("responses")
var responses_text: String? = null
constructor(){
}
}
And finally the calling function:
fun getUtterancesFromWebservice (){
val apiService = ApiInterface.create()
val call = apiService.getUtteranceDetails()
call.enqueue(object: Callback<UtteranceResponse> {
override fun onResponse(call: Call<UtteranceResponse>, response: retrofit2.Response<UtteranceResponse>?) {
if (response != null) {
if (response.body()?.utterances != null){
var list: List<Utterance> = response.body()?.utterances!!
val utterances: Utterance = list[0]
//storeUtterancesFromList(list)
} else {
Log.d ("Response:", response.body().toString())
}
}else{
Log.d ("responseResult", "NULL")
}
}
override fun onFailure(call: Call<UtteranceResponse>, t: Throwable) {
Log.e("SHIT", t.toString())
}
})
}
UPDATE My API Interface as well:
@GET("bins/1ahazo")
abstract fun getUtteranceDetails():Call<UtteranceResponse>
companion object Factory {
const val BASE_URL = "https://api.myjson.com/"
fun create(): ApiInterface {
val gson = GsonBuilder().setPrettyPrinting().create()
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
return retrofit.create(ApiInterface::class.java)
}
}
回答1:
You are returning single object not list. Change Call<UtteranceResponse>
in ApiInterface to
Call<List<Utterance>>
and for converting list to string list to string and string to list
class Utterance: SugarRecord {
@SerializedName ("langs")
var langs: List<String?>? = null
@SerializedName ("utts")
var utterances_text: String? = null
var utterances_tts: List<String?>? = null
@SerializedName ("responses")
var responses_tex:List<List<String?>?>? = null;
constructor(){
}
}
来源:https://stackoverflow.com/questions/52787794/how-to-get-gson-retrofit-to-serialize-and-map-an-array-from-a-json-response-in