【问题标题】:Kotlin Json Question Expected a string but was BEGIN_OBJECT at pathKotlin Json 问题期望一个字符串,但在路径上是 BEGIN_OBJECT
【发布时间】:2019-04-23 00:05:20
【问题描述】:

尝试一些不同的方法来解析不太用户友好的嵌套 Json。使用记录器,我可以看到正确输入的结果,但日志显示错误

  com.squareup.moshi.JsonDataException: Expected a string but was BEGIN_OBJECT at path $.capabilities[1]

我一生都无法弄清楚如何解析 Attribute 数组。我试过做<List<Attribute>> 和属性,它不会改变结果。有没有办法将 Attribute 数组转换为列表? 对 Android 编码非常陌生,因此寻求帮助。

要解析的 JSON

{
    "id": "65",
    "name": "Switch - Kitchen",
    "label": "Switch - Kitchen",
    "attributes": [
        {
            "name": "switch",
            "currentValue": "off",
            "dataType": "ENUM",
            "values": [
                "on",
                "off"
            ]
        }
    ],
    "capabilities": [
        "Switch",
        {
            "attributes": [
                {
                    "name": "switch",
                    "dataType": null
                }
            ]
        },
        "Configuration",
        "Refresh",
        "Actuator"
    ],
    "commands": [
        "configure",
        "flash",
        "off",
        "on",
        "refresh",
        "refresh"
    ]
}

设备详情

data class DeviceDetails(
    @Json(name="CapabilitiesList")
    var attributeList: Attribute,
    @Json(name="CapabilitiesList")
    val capabilities: List<String>,
    @Json(name="CommandsList")
    val commands: List<String>,
    var id: String = "",
    var label: String = "",
    var name: String = ""

)

data class Attribute(
    val currentValue: String,
    val dataType: String,
    val name: String,
    @Json(name="AttributesValues")
    val values: List<String>
)

DeviceDetailsAPI

interface DeviceDetailsAPI {
        @GET("devices/65")
        fun getDeviceDetails(@Query("access_token") access_token: String):
            Deferred<DeviceDetails>

    companion object{
        operator fun invoke(): DeviceDetailsAPI {
            //Debugging URL//
            val interceptor : HttpLoggingInterceptor = HttpLoggingInterceptor().apply {
                this.level = HttpLoggingInterceptor.Level.BODY }
            val client : OkHttpClient = OkHttpClient.Builder().apply {
                this.addInterceptor(interceptor)}.build()
            //Debugging URL//


            val okHttpClient = OkHttpClient.Builder()
                .build()

            return Retrofit.Builder()
                .client(okHttpClient)
                .baseUrl("http://xxx.xxx.xxx.xxx/apps/api/109/")
                .addCallAdapterFactory(CoroutineCallAdapterFactory())
                .addConverterFactory(MoshiConverterFactory.create())
                .client(client)
                .build()
                .create(DeviceDetailsAPI::class.java)
        }
    }
}

主活动

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val API_KEY = "xxxxxxxx"
        val testapiService = DeviceListAPI()
        val testapiDetails = DeviceDetailsAPI()

        //GlobalScope.launch (Dispatchers.Main) {
            //val DeviceListAPI = testapiService.getAllDevices(access_token = API_KEY).await()
            //textViewID.text = DeviceListAPI.toString()
        //}

        GlobalScope.launch (Dispatchers.Main) {
            val DeviceDetailsAPI = testapiDetails.getDeviceDetails(access_token = API_KEY).await()
            textViewID.text = DeviceDetailsAPI.toString()
        }

    }

}

【问题讨论】:

    标签: android json kotlin retrofit2 moshi


    【解决方案1】:

    明显的问题是 JSON 块中的 "capabilities": ... 是混合类型列表,但您将其声明为 val capabilities: List&lt;String&gt;。因此,当它击中时它会失败

      {
        "attributes": [
          {
            "name": "switch",
            "dataType": null
          }
        ]
      },
    

    项目。很难猜测此项目与capabilities 的关系,但就目前而言,这似乎需要一个相当复杂的custom Moshi adapter 才能将其解析为有意义的数据结构。

    【讨论】:

    • 当它到达"capabilities": ["Switch", { 这部分时实际上失败了,因为它期待String 的列表并且它找到了一个对象
    • 你是对的!所以我的功能块被列为 List 但它得到一个对象。任何建议如何做到这一点并使其发挥作用?
    • 您能否让 API 开发人员返回一个结构更统一的对象,或者至少记录返回的对象架构?仅从这个示例中,很难判断对象的一般模式实际上是什么,因此不可能知道如何从中构造有用的数据结构。
    • 我已经问过了,但我怀疑它会去任何地方。如果它们不改变,我的适配器必须做什么?我已经查看了“案例”陈述,但目前这些都超出了我的想象。
    • 至少 API 应该在某处有文档化的架构。如果没有,你只是在玩猜谜游戏。远不理想,但另一种可能的方法是确定您从 API 中的最低需求并编写自定义 Moshi 适配器以忽略其他所有内容。当然,这并不容易,而且您可能需要比 SO 获得的更多帮助。
    猜你喜欢
    • 1970-01-01
    • 2020-12-10
    • 1970-01-01
    • 1970-01-01
    • 2021-09-23
    • 1970-01-01
    • 2018-06-26
    • 2020-03-23
    • 1970-01-01
    相关资源
    最近更新 更多