android 莫希适配器忽略多态列表中的坏元素

92vpleto  于 2023-08-01  发布在  Android
关注(0)|答案(1)|浏览(111)

我有一个由后端发送的多态内容列表。我使用PolymorphicJsonAdapterFactory将其解析为Kotlin对象。一切正常。当后端发送一个未知类型的元素时,我应用一个默认值是没有问题的。
当后端发送具有可识别类型的错误元素(缺少必需属性)时,就会出现问题。在这种情况下,莫希停止并抛出JsonDataException。我想忽略这些因素。
我看到了this线程,但它只涉及一种类型的列表。
到目前为止,我能找到的唯一解决方案是让Kotlin数据类上的每个字段都是可选的,然后过滤掉。但这并不理想。

示例

让我们假设我有这个:

enum class Type {
   FISH,
   BIRD
}

sealed class Animal(val type: Type) {
   data class Fish(
     val requiredField : String,
   ): Animal(Type.FISH)
   data class Bird(
     val requiredField : String,
   ): Animal(Type.BIRD)
}

字符串
我收到一份动物名单。
所以我有:

PolymorphicJsonAdapterFactory.of(Animal::class.java, "type")
            .withSubtype(Fish::class.java, Type.FISH)
            .withSubtype(Bird::class.java, Type.BIRD)
            .withSubtype(Input::class.java, ActionType.input.name))
            .withDefaultValue(UnknownEntity())


这将完美地处理这个json:

{
  "animals": [
    {
      "type": "FISH",
      "requiredField": "blablabla",
    },
    {
      "type": "ANIMAL",
      "requiredField": "blablabla"
    },
    {
       "type": "Nothing",
    }
  ]
}


但不是这一个,因为鱼所需的字段是失踪失踪:

{
  "animals": [
    {
      "type": "FISH",
    },
    {
      "type": "ANIMAL",
      "requiredField": "blablabla"
    },
  ]
}


你对此有什么解决方案吗?看起来是个很正常的用例

kb5ga3dv

kb5ga3dv1#

我使用了我的SkipBadElementsListAdapter从你的链接线程,它似乎做你想要的。如果我误解了,请纠正我(最好是用演示测试用例)。

fun main() {
  val animalJsonAdapterFactory = PolymorphicJsonAdapterFactory.of(Animal::class.java, "type")
    .withSubtype(Animal.Fish::class.java, Type.FISH.name)
    .withSubtype(Animal.Bird::class.java, Type.BIRD.name)
  val moshi = Moshi.Builder()
    .add(SkipBadElementsListAdapter.Factory)
    .add(animalJsonAdapterFactory)
    .build()
  val animalsJsonAdapter =
    moshi.adapter<List<Animal>>(Types.newParameterizedType(List::class.java, Animal::class.java))
  println(animalsJsonAdapter.fromJson(encoded))
}

enum class Type {
  FISH,
  BIRD
}

sealed class Animal(val type: Type) {
  @JsonClass(generateAdapter = true)
  data class Fish(
    val requiredField: String,
  ) : Animal(Type.FISH)

  @JsonClass(generateAdapter = true)
  data class Bird(
    val requiredField: String,
  ) : Animal(Type.BIRD)
}

val encoded = """
  [
    {
      "type": "FISH",
      "requiredField": "blablabla"
    },
    {
      "type": "BIRD",
      "requiredField": "blablabla"
    },
    {
      "type": "BIRD"
    }
  ]
""".trimIndent()

字符串
这将打印[Fish(requiredField=blablabla), Bird(requiredField=blablabla)]。它忽略了不好的元素,就像你希望它做的那样。

相关问题