2017-10-13 2 views
3

EDITED:Gsonまたはモシ:POJOのフィールドが2種類を持つことができ、フィールドのいずれかに保存する方法を

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ができます

ここ

は私が持っているJSON文字列がありますサーバーからの文字列。ここでのポイントは、その後、私は任意のPOJO

class Temp1 { 
    // field1 here 
    // field2 here 

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

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

} 

にそれをそれらをデシリアライズしたい1または動的値(この場合のフィールド3は、文字列またはint型可能である)を有することができる複数のフィールド

がある可能性がありますサーバーから送信された値がIntである場合は、値をfield3Intに設定することを意味します。 Stringの場合はfield3Stringに設定します。

動的な値を持つフィールドを持つ他のPOJOが存在する可能性があります。

彼の答えはSerjに感謝しますが、実際の状況を示すために質問を編集した後も、TypeAdapterクラスで問題なく動作します。

Btw。あなたは多型デシリアライズ機能を形成活用できるMoshi

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

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

do '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

:私はこのようなRetrofit2でこれを使用しています。 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のおかげです。 Btw、私は質問を編集し、@FromJson fun fromJson(読者:JsonReader)の部分で苦労しています。助けが必要です= / – iori24

関連する問題