草庐IT

android - json 枚举反序列化破坏了 kotlin 空安全

coder 2023-12-22 原文

我使用 Kotlin 数据类GSON 反序列化 JSON 模式,并实现默认值以防止 JSON 中出现空对象。此外,使用 @SerializedName 注释将 JSON int 枚举映射到 Kotlin 枚举值:

data class Person(@SerializedName("name")
           val name: String = ",
           @SerializedName("age")
           val age: Int = 0,
           @SerializedName("hairColor")
           val hairColor: Color = Color.NONE)

enum class Color{
    @SerializedName("1")
    BROWN,
    @SerializedName("2")
    BLONDE,
    NONE
}

专注于枚举反序列化 - 这适用于字段与已知枚举相匹配或字段完全不存在于 JSON 中的情况,在这种情况下将实现默认枚举。

但是 - 如果 JSON 中接收到的枚举没有映射到我的 kotlin 枚举中的已知枚举值 - 生成的反序列化枚举将为空!!

{"name":"Joe","age":10,"hairColor":1} ->
Person(name=Joe, age=10, hairColor=BROWN)

{"name":"Jim"} ->
Person(name=Jim, age=0, hairColor=NONE)

{"name":"Jeff", "age":8,"hairColor":3) ->
Person(name=Jane, age=8, hairColor=null)

Gson 通过将 null 分配给非 null 类型来欺骗 Kotlin 的 null 安全机制。 问题 - 如何将未知的 JSON 枚举映射到默认的 Kotlin 枚举?我的目标是通过简单的实现来维护空安全。

附言- 我知道我可以将 JSON 枚举解析为 Ints,然后将它们反序列化,或者使用支持字段和自定义 getter,但我喜欢直接解析为 Kotlin 枚举的优雅和类型安全。

最佳答案

我为 Gson 编写了一个 Kotlin 包装器(称为 Arson),它将缺失的默认值添加到反序列化的对象中。除此之外,它还会检查违反 Kotlin 非空安全性的空值。

查看:https://github.com/taskbase/arson

在你的项目中使用它:

<dependency>
    <groupId>com.taskbase.arson</groupId>
    <artifactId>arson</artifactId>
    <version>1.0</version>
</dependency>

class ArsonTest {

    @Test
    fun testEnumDeserialization() {
        val json = "{'name':'Jim', 'hairColor':'3'}"

        // Gson deserializes the value to null
        val p1 = Gson().fromJson(json, Person::class.java)
        assertNull(p1.hairColor)

        // The wrapper replaces null with the default value
        val p2 = Arson(gson = Gson()).fromJson(json, Person::class.java)
        assertEquals(Color.NONE, p2.hairColor)
    }
}

data class Person(
    val name: String = "",
    val age: Int = 0,
    val hairColor: Color = Color.NONE
)

enum class Color {
    @SerializedName("1")
    BROWN,
    @SerializedName("2")
    BLONDE,
    NONE
}

我也在为 Gson 缺乏 Kotlin 支持而苦恼。 Gson 是 Java 库,不了解 Kotlin 的类型系统。我测试了其他几个 JSON 库,但没有一个效果很好。因此,我编写了一个函数,该函数使用 Kotlin 反射库来创建对象的深拷贝,以添加缺少的默认值。

关于android - json 枚举反序列化破坏了 kotlin 空安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54733643/

有关android - json 枚举反序列化破坏了 kotlin 空安全的更多相关文章

  1. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  2. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  3. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  4. ruby - 如何安全地删除文件? - 2

    在Ruby中是否有Gem或安全删除文件的方法?我想避免系统上可能不存在的外部程序。“安全删除”指的是覆盖文件内容。 最佳答案 如果您使用的是*nix,一个很好的方法是使用exec/open3/open4调用shred:`shred-fxuz#{filename}`http://www.gnu.org/s/coreutils/manual/html_node/shred-invocation.html检查这个类似的帖子:Writingafileshredderinpythonorruby?

  5. ruby-on-rails - 如何使用 Rack 接收 JSON 对象 - 2

    我有一个非常简单的RubyRack服务器,例如:app=Proc.newdo|env|req=Rack::Request.new(env).paramspreq.inspect[200,{'Content-Type'=>'text/plain'},['Somebody']]endRack::Handler::Thin.run(app,:Port=>4001,:threaded=>true)每当我使用JSON对象向服务器发送POSTHTTP请求时:{"session":{"accountId":String,"callId":String,"from":Object,"headers":

  6. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  7. ruby - 用 YAML.load 解析 json 安全吗? - 2

    我正在使用ruby2.1.0我有一个json文件。例如:test.json{"item":[{"apple":1},{"banana":2}]}用YAML.load加载这个文件安全吗?YAML.load(File.read('test.json'))我正在尝试加载一个json或yaml格式的文件。 最佳答案 YAML可以加载JSONYAML.load('{"something":"test","other":4}')=>{"something"=>"test","other"=>4}JSON将无法加载YAML。JSON.load("

  8. ruby-on-rails - OS X Mavericks 破坏了 rbenv? - 2

    最近,我安装了OSXMavericks,它似乎弄乱了我的开发环境。我在运行“railsnewfirst_app”后收到此消息:Youruseraccountisn'tallowedtoinstalltothesystemRubygems.Youcancancelthisinstallationandrun:bundleinstall--pathvendor/bundletoinstallthegemsinto./vendor/bundle/,oryoucanenteryourpasswordandinstallthebundledgemstoRubygemsusingsudo.Pass

  9. ruby-on-rails - 安全地显示使用回形针 gem 上传的图像 - 2

    默认情况下:回形针gem将所有附件存储在公共(public)目录中。出于安全原因,我不想将附件存储在公共(public)目录中,所以我将它们保存在应用程序根目录的uploads目录中:classPost我没有指定url选项,因为我不希望每个图像附件都有一个url。如果指定了url:那么拥有该url的任何人都可以访问该图像。这是不安全的。在user#show页面中:我想实际显示图像。如果我使用所有回形针默认设置,那么我可以这样做,因为图像将在公共(public)目录中并且图像将具有一个url:Someimage:看来,如果我将图像附件保存在公共(public)目录之外并且不指定url(同

  10. ruby-on-rails - carrierwave:在序列化动态属性上安装 uploader - 2

    首先,我使用的是rails3.1.3和来自master的carrierwavegithub仓库的分支。我使用after_init钩子(Hook)来确定基于属性的字段页面模型实例并为这些字段定义属性访问器将值存储在序列化哈希中(希望它清楚我是什么谈论)。这是我正在做的事情的精简版:classPage省略mount_uploader命令让我可以访问我想要的属性。但是当我安装uploader时出现错误消息说“nil类的未定义新方法”我在源代码中读到有方法read_uploader和扩展模块中的write_uploader。我如何必须覆盖这些来制作mount_uploader命令使用我的“虚拟

随机推荐