Retrofit/Gson报错:Expected BEGIN_OBJECT but was BEGIN_ARRAY及JSON问题
问题根源与解决方案
Flask端修改:返回带列名的JSON
你当前用cursor.fetchall()拿到的是无列名的元组列表,所以jsonify返回的是纯数组,没有字段名,导致Android端无法映射到TestPin的属性。要返回带列名的JSON,需要把元组转成字典:
cursor.execute('SELECT * FROM TestDB') # 获取所有列名 columns = [desc[0] for desc in cursor.description] # 把每一行元组转换成字典(列名作为键) Testdata = [dict(zip(columns, row)) for row in cursor.fetchall()] print(Testdata) cursor.close() conn.close() return jsonify(Testdata)
这样返回的JSON格式会变成:
[ {"id":1, "name":"Test", "location":"010100000085EB51B81E0524400000000000B49840", "day1":"Monday", "day2":"Tuesday", "day3":"wed"}, {"id":2, "name":"Test2", "location":"010100000085EB51B81E0524400000000000B49840", "day1":"Monday", "day2":"Tuesday", "day3":"wed"} ]
Android端调整:确保字段映射正确
改成Call<List<TestPin>>是正确的,但要保证TestPin的字段名和Flask返回的JSON键完全一致,或者用@SerializedName做映射:
比如你的数据库列名如果是id、name、location、day1、day2、day3,那TestPin应该这么写:
data class TestPin( val id: Int, val name: String, val location: String, @SerializedName("day1") val monday: String, // 如果想给字段起别名,用这个注解 val day2: String, val day3: String )
同时检查Retrofit初始化是否添加了Gson转换器:
val retrofit = Retrofit.Builder() .baseUrl("你的Flask API地址") .addConverterFactory(GsonConverterFactory.create()) .build() val testAPI = retrofit.create(TestAPI::class.java)
关键误区说明
- Flask端:
fetchall()返回的是元组集合,不是字典,必须手动关联列名才能生成带键的JSON,否则Android端无法识别字段。 - Android端:初始的
TestResponse期望API返回一个包含Tests数组的对象,但Flask返回的是直接的数组,所以会报Expected BEGIN_OBJECT but was BEGIN_ARRAY错误,改成Call<List<TestPin>>是正确的,但要确保字段映射匹配。
内容的提问来源于stack exchange,提问作者Bizes
相关产品推荐
相关产品推荐

