大佬教程收集整理的这篇文章主要介绍了使用 Kotlin lenient Json Serialization 时如何报告未知的 json 字段,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我当前的项目采用改造 kotlin Json 序列化。
我已将 Json 配置如下:-
杰森{ ignoreUnkNownKeys = true isLenIEnt = true }
这允许我的应用程序解析带有未知字段的 Json,但是我想报告
我收到的所有未知 Json 字段。
我看不出有什么方法可以实现这一目标。
使用 Jackson 更快的 xml Json 库,这很容易实现,但我希望尽可能少地使用 3rd 方库。
有什么办法可以让 Json 序列化并捕获所有未知的 Json 字段吗?
像 the other answer 一样,我将在此答案中发布的代码比我推荐的正确解决方案更像是一种黑客攻击,但与其他答案不同:
也就是说,真正的解决方案可能是 kotlinx.serialization
库 and I encourage you to post a feature @R_675_10613@est on GitHub 中缺少的功能。维护人员非常积极响应并乐于接受建议!
从源代码 jccampanero linked to in comments 中可以看出,引入此行为的正确抽象级别应在 StreamingJsonDecoder
中。因此,与下面的解决方案不同的解决方案是 to implement a custom format 并复制/粘贴所有 Json
代码,并在 StreamingJsonDecoder.handleUnknown
中添加少量代码。同样,不是我推荐的东西。
以下内容可能适用于 (3) 的情况。
abstract class ReportUnknownFieldsserializer<T : Any>(
private val tserializer: Kserializer<T>
) : JsonTransformingserializer<T>( tserializer )
{
override fun transformDeserialize( element: JsonElement ): JsonElement
{
if ( element is JsonObject )
{
val expectedNames = tserializer.descriptor.elementNames
val actualNames = element.keys
val unexpectedNames = actualNames.minus( expectedNames )
println( unexpectedNames )
}
return element
}
}
@serializable
data class SomeObject( val expected: String )
object SomeObjectserializer
: ReportUnknownFieldsserializer<SomeObject>( SomeObject.serializer() )
@serializable
data class Wrapper(
@serializable( SomeObjectserializer::class )
val someObject: SomeObject
)
class ReportUnknownFieldsserializerTest
{
@Test
fun unknown_fields_are_reported()
{
val json = Json { ignoreUnknownKeys = true; isLenient = true }
val serialized = """{"someObject":{"expected":"normal","unexpected":"oh"}}"""
// Outputs "[unexpected]"
val wrapper: Wrapper = json.decodeFromString( serialized )
}
}
一个 JsonTransformingserializer
is used,它在反序列化时将预期的字段名称与指定的字段名称进行比较。对于要启用此行为的每个可序列化类成员,您需要应用基 ReportUnknownFieldserializer
的实例化。
因此,如前所述,这可能不适用于您的实际用例。您不想为每个成员字段类型创建自定义序列化程序,然后您必须无处不在。如果这是您的用例,您可能希望将其作为 JSON 序列化格式的一项功能请求给 kotlinx.serialization
的维护者。它可能会涉及 Json
类上的额外配置选项,例如,以您喜欢的任何方式处理未知字段的 lambda 回调。
您可以使用以下解决方法:将您的 Json
格式包装成另一种格式,它将尝试以严格的方式(使用 ignoreUnknownKeys = false
)解码输入字符串,如果失败,则报告未知键并回退到原始 Json
格式。
@ExperimentalserializationApi
class JsonLoggingUnknownFields(private val kotlinx: Json) : StringFormat by kotlinx {
private val kotlinxStrict = Json(from = kotlinX) { ignoreUnknownKeys = false }
override fun <T> decodeFromString(deserializer: DeserializationStrategy<T>,String: String): T {
val json = kotlinx.parseToJsonElement(String)
return try {
kotlinxStrict.decodeFromJsonElement(deserializer,json)
} catch (e: serializationException) {
val unknownKeysInTopLevelJsonObject = if (json is JsonObject) {
val actualFields = json.keys
val expectedFields = deserializer.descriptor.elementNames
actualFields - expectedFields
} else emptySet()
log.debug(
if (unknownKeysInTopLevelJsonObject.isnotEmpty()) "Encountered unknown keys: $unknownKeysInTopLevelJsonObject\nCurrent input: $String"
else e.message!!.replace("Use 'ignoreUnknownKeys = true' in 'Json {}' builder to ignore unknown keys.\n","")
)
kotlinx.decodeFromJsonElement(deserializer,json)
}
}
}
请注意,此技巧将仅针对顶级 JSON 对象报告所有未知的 JSON 字段,对于嵌套的 JSON 对象(或 JSON 数组)仅第一个遇到未知的字段将被报告(如果顶级 JSON 对象中没有未知字段)。
用法:
@serializable
data class Obj(val x: Int = 0)
@serializable
data class obj2(val obj: Obj)
@ExperimentalserializationApi
fun main() {
val kotlinx = Json {
ignoreUnknownKeys = true
isLenient = true
}
val kotlinxWithLogging = JsonLoggingUnknownFields(kotlinX)
val input1 = "{\"unknownkey1\": 1,\"unknownKey2\": 1,\"x\" : 11}"
println(kotlinxWithLogging.decodeFromString<Obj>(input1)) //Encountered unknown keys: [unknownkey1,unknownKey2]
val input2 = "[{\"unknownkey1\": 1,\"unknownKey2\": 1}]"
println(kotlinxWithLogging.decodeFromString<List<Obj>>(input2)) //Encountered unknown key 'unknownkey1'.
val input3 = "{\"obj\": {\"unknownkey1\": 1,\"unknownKey2\": 1}}"
println(kotlinxWithLogging.decodeFromString<obj2>(input3)) //Encountered unknown key 'unknownkey1'.
}
以上是大佬教程为你收集整理的使用 Kotlin lenient Json Serialization 时如何报告未知的 json 字段全部内容,希望文章能够帮你解决使用 Kotlin lenient Json Serialization 时如何报告未知的 json 字段所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。