Gson o Moshi: campo en POJO podría tener 2 types, cómo save en cualquiera de los campos

EDITADO:

Aquí está la cadena json que tengo:

json#1 { [ { field1 : "" field2 : 0 field3 : "Amount not fixed" or field : 250 // this field can be string or int }, { field1 : "" field2 : 0 field3 : "Amount not fixed" or field : 250 // this field can be string or int } ] } json#2 { field1 : "" field2 : 0 field3 : "Amount not fixed" or field : 250 // this field can be string or int } 

O podría cualquier cadena json del server. El punto aquí es que podría haber 1 o más campos que pueden tener un valor dynamic (en este caso, field3 puede ser una cadena o int)

Entonces quiero deserializarlos a cualquier POJO

 class Temp1 { // field1 here // field2 here @SerializedName("field3") val field3Int: Int? = null @SerializedName("field3") val field3String: String? = null } 

Significa que si el valor enviado desde el server es un Int , quiero establecer el valor en field3Int . Si es una String , establezca en field3String .

Podría haber otros POJO que tengan este tipo de campos que pueden tener un valor dynamic.

Gracias a Serj por su respuesta, pero todavía no puedo hacer que funcione en la class TypeAdapter después de editar la pregunta para mostrar mi situación real.

Por cierto. Yo uso esto con Retrofit2 así:

 val moshi = Moshi.Builder() .add(MultitypeJsonAdapterAdapter()) .build() return Retrofit.Builder().baseUrl(baseUrl) .addConverterFactory(MoshiConverterFactory.create(moshi)) .client(httpClient.build()) .build() 

Con Moshi puedes aprovechar la function de deserialization polimórfica. Simplemente escriba un adaptador personalizado que usará JsonReader#readJsonValue() . Vea el código a continuación:

 data class Multitype constructor(val fieldInt: Int?, val fieldString: String?) { constructor(fieldInt: Int) : this(fieldInt, null) constructor(fieldString: String) : this(null, fieldString) } class MultitypeJsonAdapterAdapter { @FromJson fun fromJson(reader: JsonReader): Multitype { val jsonValue = reader.readJsonValue() as Map<String, Any?> val field = jsonValue["field"] return when (field) { is String -> Multitype(field) is Double -> Multitype(field.toInt()) // readJsonValue parses numbers as Double else -> throw JsonDataException("Expected a field of type Int or String") } } @ToJson fun toJson(writer: JsonWriter, value: Multitype?) { TODO("not implemented") } } class MultitypeJsonAdapterAdapterTest { @Test fun check() { val moshi = Moshi.Builder() .add(MultitypeJsonAdapterAdapter()) .add(KotlinJsonAdapterFactory()) .build() val adapter = moshi.adapter(Multitype::class.java) val fromJson1 = adapter.fromJson("""{ "field": 42 }""") assertThat(fromJson1).isEqualTo(Multitype(42)) val fromJson2 = adapter.fromJson("""{ "field": "test" }""") assertThat(fromJson2).isEqualTo(Multitype("test")) } } 

Creo que obtuve lo que quiero lograr. Y no es necesario usar ningún adaptador. Si un campo puede tener cualquier tipo dynamic, debe declararlo como Cualquiera en su POJO. Luego, si desea usar su valor real, solo necesita verificar su tipo y emitirlo. Entonces al POJO le gustaría esto:

 class Temp1 { // field1 here // field2 here @SerializedName("field3") val field3: Any? = null fun getField3Str() : String { return when (field3) { is String -> field3 as String is Int -> { "%d".format(field3 as Int) } else -> "" } } } 
  • Analizando json con API remota rota
  • Moshi en Android Kotlin - ENUM como key MutableMap que se convierte en String cuando se desexcita