如果Gson序列化失败,如何跳过字段?

例如,服务器响应#1具有name对象:

     {
       "id":"vfa45f42","name": { 
                "firstName":"UserFirstName","lastName":"UserLastName"
         }
    }

但是有时服务器响应#2具有name用户其他对象的字符串(这是因为服务器具有MongoDB,而在v1处是String,而在v2处是Object) :

    {
        "id":"abfaf453","name":"Onesentenceusername"
    }

因此,如果我使用响应#2进行以下操作:

val type = object : TypeToken<User>() {}.type
gson.fromJson(responseString,type)

其中

data class User(val id:String,val name: Name)

data class Name(val firstName: String,val lastName: String)

错误是:

java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line ...

如果它是json上的name = null,我希望制作String

steve313 回答:如果Gson序列化失败,如何跳过字段?

保留实际的类employeeUser,您可以创建一个自定义TypeAdapter并从单个Name字符串或自己阅读即可完成JSON对象。

Name

然后,您可以将此类型的适配器添加到gson构建器中。

name

在每种情况下,它将正确地反序列化名称并产生完整的class NameAdapter : TypeAdapter<Name>() { @Throws(IOException::class) override fun read(reader: JsonReader): Name? { return when(reader.peek()) { // if { "name": null } JsonToken.NULL -> { reader.nextNull() null } // if { "name": "SomeString" } JsonToken.STRING -> { Name(reader.nextString(),"") } //if { "name": { "firstName": "some","lastName": "thing" } JsonToken.BEGIN_OBJECT -> { var firstName = "" var lastName = "" reader.beginObject() while (reader.hasNext()) { val peek = reader.peek() if(peek == JsonToken.END_OBJECT) break else if(peek == JsonToken.NAME) { when(reader.nextName()) { // it will produce an exception if it isn't a string "firstName" -> firstName = reader.nextString() "lastName" -> lastName = reader.nextString() } } } reader.endObject() Name(firstName,lastName) } else -> throw IOException("Unable to parse a name") } } @Throws(IOException::class) override fun write(writer: JsonWriter,value: Name?) { if(value == null) { writer.nullValue() return } writer.beginObject() writer.name("firstName") writer.value(value.firstName) writer.name("lastName") writer.value(value.lastName) writer.endObject() } } 类。

,

不知道它是否可以直接为您提供帮助,但是对于同一情况,我对Kotlinx.Serializartion库做了以下操作:

命名为JsonElement类型

val name: JsonElement

然后创建自定义反序列化功能,例如:

fun getName(): Name? =
    if (name is JsonObject) {
        // deserialize Name normally
    } else {
        // create Name by hand,only with 'name' property... 
    }

希望这会有所帮助。

,

找到了解决方案,只需要使用其中之一:

1。 第一个解决方案:

data class User(val id:String,@JsonAdapter(FailSafeNameTypeAdapter::class) val name: Name)

其中

class FailSafeNameTypeAdapter internal constructor(private val delegate: TypeAdapter<Name>) : TypeAdapter<Name>() {

    @Throws(IOException::class)
    override fun write(writer: JsonWriter,value: Name?) {
        if (value == null) {
            writer.nullValue()
            return
        }

        // This catches non-proxied collections AND initialized proxied collections
        delegate.write(writer,value)
    }

    @Throws(IOException::class)
    override fun read(reader: JsonReader): Name? {
        val peek = reader.peek()
        if (peek == STRING) {
            reader.skipValue()
            return null
        }
        return delegate.read(reader) as Name
    }

}

第二个解决方案

data class User(val id:String,@JsonAdapter(FailSafePriceTypeAdapterFactory::class) val name: Name)

其中

class FailSafePriceTypeAdapterFactory : TypeAdapterFactory {
    override fun <T> create(gson: Gson,type: TypeToken<T>): TypeAdapter<T>? {
        if (Price::class.java.isAssignableFrom(type.rawType)) {
            val delegate = gson.getDelegateAdapter<T>(this,type) as TypeAdapter<Price>

            return FailSafePriceTypeAdapter(delegate) as TypeAdapter<T>
        }

        return null
    }

    companion object {
        val FACTORY: TypeAdapterFactory = FailSafePriceTypeAdapterFactory()
    }
}
    3。

第三种解决方案

val gson = GsonBuilder()
            .setFieldNamingPolicy(FieldNamingPolicy.IDENTITY)
            .apply {
                registerTypeAdapterFactory(FailSafePriceTypeAdapterFactory.FACTORY)

            }
            .create()
本文链接:https://www.f2er.com/3109634.html

大家都在问