2017-10-13 20 views
3

편집 한 모든 필드에 저장하는 2 종류, 수 :GSON 또는 모시 : POJO 필드가 어떻게

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 문자열입니다 서버의 문자열. 여기서 포인트는 동적 값을 가질 수 하나 개 이상의 필드가있을 수 있습니다 나는

class Temp1 { 
    // field1 here 
    // field2 here 

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

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

} 

에게 어떠한 POJO에 그들을 직렬화하는 그런

(이 경우 FIELD3 문자열 또는 INT 될 수 있습니다) 서버에서 보낸 값이 Int 인 경우이 값을 field3Int으로 설정하고 싶습니다. String 인 경우 field3String으로 설정하십시오.

동적 인 값을 가질 수있는 필드가있는 다른 POJO가있을 수 있습니다.

Serj에게 감사의 말을 전합니다. 그러나 실제 상황을 보여주기 위해 질문을 편집 한 후에도 TypeAdapter 클래스에서 작동하지 않습니다.

btw. 나는이 같은 Retrofit2 이것을 사용 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

당신은 다형성 직렬화 기능을 형성 활용할 수 있습니다. 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 재미 fromJson (독자 : JsonReader) 부분에 고투. 도움이 필요함 = / – iori24