2017-10-13 20 views
3

編着:GSON或莫西:在POJO領域可以有2種類型,如何保存到任何領域

這裏是JSON字符串,我有:

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 
} 

,或者它可以任意JSON字符串從服務器。這裏的關鍵是有可能是,可能有一個動態值1個或多個字段(是這種情況下字段3可以是一個字符串或INT)

然後我想他們反序列化到任何POJO

class Temp1 { 
    // field1 here 
    // field2 here 

    @SerializedName("field3") 
    val field3Int: Int? = null 

    @SerializedName("field3") 
    val field3String: String? = null 

} 

它意味着如果從服務器發送的值是Int,我想將值設置爲field3Int。如果它是String,則設置爲field3String

可能有其他POJO會擁有這些可能具有動態價值的字段。

感謝Serj對他的回答,但在編輯問題以顯示我的真實情況後,我仍無法使其在TypeAdapter類上工作。

Btw。我用這個與Retrofit2這樣的:

val moshi = Moshi.Builder() 
        .add(MultitypeJsonAdapterAdapter()) 
        .build() 
      return Retrofit.Builder().baseUrl(baseUrl) 

        .addConverterFactory(MoshiConverterFactory.create(moshi)) 
        .client(httpClient.build()) 
        .build() 
+0

做'field1'和'field2'有固定類型還是動態的? –

+0

也在你的例子中,'json#1'不是一個有效的JSON。 –

+0

@SerjLotutovici任何字段都可以是動態的。在這個pojo,它唯一的領域3。 – iori24

回答

1

我想我得到了我想達到的。並且不需要使用任何適配器。 如果一個字段可以有任何動態類型,則需要在POJO中將其聲明爲Any。那麼如果你想使用它的實際值,你只需要檢查它的類型並投射它。所以POJO應該這樣:

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 -> "" 
     } 
    } 
} 
2

隨着Moshi您可以利用形成多態的反序列化功能。只需編寫一個將使用JsonReader#readJsonValue()的自定義適配器。見下面的代碼:

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")) 
    } 
} 
+0

感謝Serj的幫助。順便說一句,我編輯了這個問題,並且我從Json(閱讀器:JsonReader)部分開始了@FromJson樂趣。需要幫助= / – iori24