首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何在使用Kotlin宽大json序列化时报告未知Json字段

如何在使用Kotlin宽大json序列化时报告未知Json字段
EN

Stack Overflow用户
提问于 2021-07-14 23:49:14
回答 2查看 472关注 0票数 2

我目前的项目采用改造kotlin json序列化。

我已将Json配置如下:

ignoreUnknownKeys =真isLenient =真}

,这允许我的应用程序使用未知字段解析Json,但是我希望报告

我收到的所有未知的Json字段。

我看不出还有什么能做到这一点。

使用Jackson更快的xml库,这是很容易实现的,但是我希望使用尽可能少的第三方库。

有什么办法可以让我得到宽大的Json序列化和捕获所有未知的Json字段?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-07-21 06:33:57

另一个答案一样,我将在这个答案中发布的代码更像是黑客,而不是我推荐的适当解决方案,但与其他答案不同:

  1. 它报告了所有未知的字段。
  2. 不依赖于异常处理逻辑(我预计它会大大增加运行时,这是一种代码味道)。
  3. 如果您希望允许/记录未知字段的可序列化对象的成员受到限制,则可能是合适的。

尽管如此,真正的解决方案可能是kotlinx.serialization我鼓励您在GitHub上发布一个特性请求中缺少的特性。维护人员是非常响应和开放的建议!

正如您可以从源jccampanero与评论链接中看到的那样,引入此行为的正确抽象级别将在StreamingJsonDecoder中。因此,与下面的解决方案不同的是实现自定义格式和复制/粘贴所有Json代码,并在StreamingJsonDecoder.handleUnknown中添加少量内容。再说一次,我不会推荐的。

在第(3)款适用的情况下,以下内容可能是适当的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 )
    }
}

反序列化时比较预期字段名和指定字段名的使用的是。对于要启用此行为的每个可序列化类成员,需要应用基ReportUnknownFieldSerializer的实例化。

因此,如前所述,这可能不适用于您的实际用例。您可能不希望为每个成员字段类型创建自定义序列化程序,然后必须在任何地方应用这些序列化程序。如果这是您的用例,您可能希望将其作为JSON序列化格式的一个特性请求给kotlinx.serialization的维护人员。它可能会在Json类上增加一个配置选项,例如,一个lambda回调,以任何您想要的方式处理未知字段。

票数 1
EN

Stack Overflow用户

发布于 2021-07-21 04:49:10

您可以使用以下解决方法:将您的Json格式包装成另一种格式,它将尝试严格地解码输入字符串(使用ignoreUnknownKeys = false),如果它失败,则报告未知的键并返回到原始的Json格式。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@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对象中没有未知字段)。

用法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@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'.
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68389876

复制
相关文章
jackson 序列化忽略未知字段: How to Ignore Unknown Properties While Parsing JSON in Java
使用 Jackson API 在Java中解析JSON时的一个常见问题是,当JSON包含未知属性时,即Java类没有与所有JSON属性对应的所有字段时,解析失败。
一个会写诗的程序员
2021/07/23
3.9K0
如何在Lua中使用json
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格局。它基于ECMAScript的一个子集。JSON选用完全独立于言语的文本格局,但是也使用了类似于C言语宗族的习气(包含C、C++、C#、Java、JavaScript、Perl、Python等)。这些特性使json调试成为抱负的数据交换言语。易于人阅览和编写,同时也易于机器解析和生成(一般用于提高网络传输速率)。
杜金房
2023/02/28
7.1K0
如何在Lua中使用json
MySQL 支持JSON字段的基本操作、相关函数及索引使用如何索引JSON字段
Mysql5.7版本以后新增的功能,Mysql提供了一个原生的Json类型,Json值将不再以字符串的形式存储,而是采用一种允许快速读取文本元素(document elements)的内部二进制(internal binary)格式,并提供了不少内置函数,通过计算列,甚至还可以直接索引json中的数据。
chenchenchen
2022/03/09
29.8K0
Springboot2.0 + Kotlin自定义json序列化不返回null字段的方法
两种方式: 第一种,在配置文件里加入如下配置: spring: jackson: default-property-inclusion: non_null 第二种:在mvc配置文件里加入如下配置: override fun extendMessageConverters(converters: MutableList<HttpMessageConverter<*>>) { converters.forEach { if (it is MappingJackson2HttpMessa
飞奔去旅行
2019/06/13
2K0
JSON序列化 反序列化 自定义属性字段
FastJson中的注解@JSONField,一般作用在get/set方法上面,常用的使用场景有下面三个: 修改和json字符串的字段映射【name】 格式化数据【format】 过滤掉不需要序列化的字段【serialize】
Qwe7
2022/04/02
1.1K0
​MySql之json_extract函数处理json字段
在db中存储json格式的数据,相信大家都或多或少的使用过,那么在查询这个json结构中的数据时,有什么好的方法么?取出String之后再代码中进行解析?
一灰灰blog
2022/05/30
13.9K0
48 - 在json 序列化时如何处理日期类型的值
1. 在json 序列化时,可以自动处理哪些数据类型 可以处理的数据类型 str int list tuple dict bool None 但datetime不支持jaon 序列化 2. 在json 序列化时,如何处理日期类型 ''' default ''' import json from datetime import datetime, date class DateToJson(json.JSONEncoder): def default(self, obj):
ruochen
2021/05/29
2K0
48 - 在json 序列化时如何处理日期类型的值
Go使用类型断言处理动态JSON字段
Go作为强类型语言,在序列化和反序列化过程中,都不可避免地需要定义结构体:在有IDL的情况下结构体可以使用工具自动生成(kitex),在无IDL的情况下就得手撸。
Steve Wang
2023/10/12
2500
Kotlin之JSON格式解析
第一步:首先导入KlaXon库,官网地址是:https://github.com/cbeust/klaxon 导入成功后我们将试着编译一个Json资源 创建Gradle 项目 导入包 repositories { jcenter() }
全栈程序员站长
2022/07/25
1K0
MySQL中的json字段
MySQL5.7.8中引入了json字段,这种类型的字段使用的频率比较低,但是在实际操作中,有些业务仍然在用,我们以此为例,介绍下json字段的操作方法:
AsiaYe
2019/12/23
9.1K0
C# Json序列化工具–Newtonsoft.Json简介和使用
Newtonsoft.Json,是.Net中开源的Json序列化和反序列化工具,官方地址:http://www.newtonsoft.com/json。
全栈程序员站长
2022/11/17
3.4K0
[C#]JSON反序列化对象--解析JSON文本
This sample deserializes JSON to an object.
科控物联
2022/06/13
1.2K0
[C#]JSON反序列化对象--解析JSON文本
在MVC中使用Json.Net序列化和反序列化Json对象
在.Net的MVC开发中,经常会使用到Json对象,于是,系统提供了JsonResult这个对象,其本质是调用.Net系统自带的Json序列化类JavaScriptSerializer对数据对象进行序列化。但是这个系统自带的Json序列化对象方法没有Json.Net好用,于是打算有些时候用Json.Net替代默认的实现。
深蓝studyzy
2022/06/16
1.2K0
golang 使用json 包 实现序列化
package main import ( "encoding/json" "fmt" ) func main() { //初始化 data := make(map[string]interface{}, 1) data["name"] = "xiaochuan" data["age"] = 23 //序列化 json_obj, err := json.Marshal(data) if err != nil { fmt.Println("err :", err) } mar
李海彬
2018/03/26
8020
【Flutter】JSON 模型转换 ( JSON 序列化工具 | JSON 手动序列化 | 根据 JSON 编写 Dart 模型类 | 在线自动根据 JSON 转换 Dart 类 )
JSON 格式比较简单的话 , 使用自带的 dart:convert 包 , 手动进行 JSON 的序列化与反序列化的操作即可 ;
韩曙亮
2023/03/29
2.8K0
【Flutter】JSON 模型转换 ( JSON 序列化工具 | JSON 手动序列化 | 根据 JSON 编写 Dart 模型类 | 在线自动根据 JSON 转换 Dart 类 )
Golang -- Json序列化
在使用Go Struct的Json Marshal的时候,通过Json To Go Struct工具可以生成结构体,但是当在结构体中只对部分属性赋值的时候,Marshal后的字符串与预期不符,如下所示:
None_Ling
2021/11/24
7670
Python json序列化
Python内置的json模块提供了非常完善的对象到JSON格式的转换。废话不多说,我们先看看如何把Python对象变成一个JSON:
py3study
2020/01/16
2.2K0
go :tag实现json字段转换
我们都知道go的struct中,如果字段需要对外使用,就需要使用首字母大写的格式,但是如果API中约定要使用小写字母开头呢?
IT工作者
2022/07/22
1.2K0
myatis puls 处理json类型字段
使用mybatis plus进行sql的映射时如果是用原生的查询方法可以将json类型的字段顺利映射到对象中,可是如果是自己来写sql进行查询json数据类型映射会出现无法映射成功,基于这种情况参考了一下mp官网的说明,先记录一下
在水一方
2022/09/23
1.8K0
myatis puls 处理json类型字段
Python序列化-json
Python 序列化是将 Python 对象转换为可以存储或传输的格式,如 JSON 或二进制格式。
玖叁叁
2023/04/18
7130

相似问题

使用json进行序列化时跳过未知项目

10

使用未知字段反序列化JSON

14

如何在JSON反序列化时忽略某些字段?

12

使用Kotlin将枚举字段序列化为JSON

2160

使用.net JSON序列化时出现Json问题

35
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文