Json Gson或Moshi:POJO中的字段可以有两种类型,如何保存到任何字段
编辑: 以下是我拥有的json字符串:Json Gson或Moshi:POJO中的字段可以有两种类型,如何保存到任何字段,json,kotlin,gson,retrofit,moshi,Json,Kotlin,Gson,Retrofit,Moshi,编辑: 以下是我拥有的json字符串: json#1 { [ { field1 : "" field2 : 0 field3 : "Amount not fixed" or field : 250 // this field can be string or int }, { field1 : "" field2 : 0
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字符串。这里的要点是可能有一个或多个字段具有动态值(在这种情况下,field3可以是字符串或int)
然后我想将它们反序列化到任何POJO
class Temp1 {
// field1 here
// field2 here
@SerializedName("field3")
val field3Int: Int? = null
@SerializedName("field3")
val field3String: String? = null
}
这意味着如果从服务器发送的值是Int
,我想将该值设置为field3Int
。如果是字符串
,则设置为field3String
可能还有其他POJO将具有此类字段,这些字段可能具有动态值
感谢Serj的回答,但在我编辑了问题以显示我的真实情况之后,我仍然无法在TypeAdapter类上使用它
顺便说一句,我将其用于改装2,如下所示:
val moshi = Moshi.Builder()
.add(MultitypeJsonAdapterAdapter())
.build()
return Retrofit.Builder().baseUrl(baseUrl)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.client(httpClient.build())
.build()
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)
}
is Double -> {
"%d".format(field3.toInt())
}
else -> ""
}
}
}
使用
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"))
}
}
数据类多类型构造函数(val-fieldInt:Int?,val-fieldString:String?){
构造函数(fieldInt:Int):这个(fieldInt,null)
构造函数(fieldString:String):这个(null,fieldString)
}
类MultitypeJsonAdapterAdapter{
@FromJson乐趣FromJson(阅读器:JsonReader):多类型{
val jsonValue=reader.readJsonValue()作为映射
val field=jsonValue[“field”]
返回时间(字段){
是字符串->多类型(字段)
is Double->multi-type(field.toInt())//readJsonValue将数字解析为Double
else->throw JsonDataException(“应为Int或String类型的字段”)
}
}
@ToJson-fun-ToJson(writer:JsonWriter,value:multi-type?){
待办事项(“未实施”)
}
}
类MultitypeJsonAdapterAdapterTest{
@测试乐趣检查(){
val moshi=moshi.Builder()
.add(MultitypeJsonAdapterAdapter())
.add(KotlinJsonAdapterFactory())
.build()
ValAdapter=moshi.adapter(Multitype::class.java)
val fromJson1=adapter.fromJson(“{”字段:42}”)
assertThat(来自JSON1.isEqualTo(多类型(42))
val fromJson2=adapter.fromJson(“{”字段“:“test”}”)
isEqualTo(多类型(“测试”))
}
}
我想我得到了我想要实现的目标。而且不需要使用任何适配器。
如果字段可以有任何动态类型,则需要在POJO中将其声明为any。然后,如果您想使用它的实际值,您只需要检查它的类型并强制转换它。所以POJO应该是这样的:
val moshi = Moshi.Builder()
.add(MultitypeJsonAdapterAdapter())
.build()
return Retrofit.Builder().baseUrl(baseUrl)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.client(httpClient.build())
.build()
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)
}
is Double -> {
"%d".format(field3.toInt())
}
else -> ""
}
}
}
谢谢Serj的帮助。顺便说一句,我编辑了这个问题,我在@FromJson-fun-FromJson(reader:JsonReader)部分苦苦挣扎。需要帮助=/do
field1
和field2
有固定的类型,或者它们也是动态的?同样在您的示例中,json#1
不是有效的json。@SerjLotutovici任何字段都可以是动态的。在这个pojo中,它是唯一的字段3。