Kotlin Json问题需要一个字符串,但在路径上为BEGIN_OBJECT

时间:2019-04-23 00:05:21

标签: android json kotlin retrofit2 moshi

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

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

我一生都无法弄清楚如何解析Attribute数组。我尝试做<List<Attribute>>和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"
    ]
}

DeviceDetails

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)
        }
    }
}

MainActivity

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()
        }

    }

}

1 个答案:

答案 0 :(得分:1)

一个明显的问题是JSON块中的"capabilities": ...是混合类型列表,但是您将其声明为val capabilities: List<String>。因此,它碰到

时会失败
  {
    "attributes": [
      {
        "name": "switch",
        "dataType": null
      }
    ]
  },

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