使用注释通过嵌套事件在 Moshi 中序列化 Null

2024-04-24

我正在尝试添加自定义注释,以便在调用时将模型中的特定值序列化为 nulltoJSON来自莫西的方法。我有一些基于此的工作response https://stackoverflow.com/questions/52254876/moshi-custom-qualifier-annotation-to-serialise-null-on-one-property-only但当我有一个嵌套对象时,它对我来说就不够了。

@JsonClass(generateAdapter = true)
data class EventWrapper(
    @SerializeNulls val event: Event?,
    @SerializeNulls val queries: Queries? = null) {

    @JsonClass(generateAdapter = true)
    data class Queries(val stub: String?)

    @JsonClass(generateAdapter = true)
    data class Event(
       val action: String?,
       val itemAction: String)
}

如果我将 null 传递给event or queries它们被序列化为:

{
    'event': null,
    'query': null
}

问题是,当事件不为空时,其中的字段如果为空(例如操作),我不想序列化。我首选的结果是这样的:

{
    'event': {
        'itemAction': "test" 
    },
    'query': null
}

但我得到的是:

{
    'event': {
        'action': null,
        'itemAction': "test" 
    },
    'query': null
}

以下是基于链接响应的自定义适配器的代码:

@Retention(RetentionPolicy.RUNTIME)
 @JsonQualifier
 annotation class SerializeNulls {
     companion object {
         var JSON_ADAPTER_FACTORY: JsonAdapter.Factory = object : JsonAdapter.Factory {

             @RequiresApi(api = Build.VERSION_CODES.P)
             override fun create(type: Type, annotations: Set<Annotation?>, moshi: Moshi): JsonAdapter<*>? {
                 val nextAnnotations = Types.nextAnnotations(annotations, SerializeNulls::class.java)

                 return if (nextAnnotations == null) {
                     null
                 } else {
                     moshi.nextAdapter<Any>(this, type, nextAnnotations).serializeNulls()
                 }
        }
    }
}

@Su-Au Hwang 在线程中的回答对我有用。这比为我们的模型创建自定义适配器更好。谢谢。

这是与 Kotlin 相同的代码:

  1. 创建一个新适配器NullIfNullJsonAdapter

    class NullIfNullJsonAdapter<T>(val delegate: JsonAdapter<T>) : JsonAdapter<T>() {
    
            override fun fromJson(reader: JsonReader): T? {
                return delegate.fromJson(reader)
            }
    
            override fun toJson(writer: JsonWriter, value: T?) {
                if (value == null) {
                    val serializeNulls: Boolean = writer.serializeNulls
                    writer.serializeNulls = true
                    try {
                        delegate.toJson(writer, value)
                    } finally {
                        writer.serializeNulls = serializeNulls
                    }
                } else {
                    delegate.toJson(writer, value)
                }
            }
    
            override fun toString(): String {
                return "$delegate.serializeNulls()"
            }
        }
    
  2. Create JsonQualifier您可以使用它来进行注释

     @Retention(AnnotationRetention.RUNTIME)
     @JsonQualifier
     annotation class SerializeNull {
         companion object {
             object Factory : JsonAdapter.Factory {
                 override fun create(type: Type, annotations: MutableSet<out Annotation>, moshi: Moshi): JsonAdapter<*>? {
                     val nextAnnotations = Types.nextAnnotations(annotations, SerializeNull::class.java)
    
                     return if (nextAnnotations == null) {
                         null
                     } else {
                         NullIfNullJsonAdapter<Any>(moshi.nextAdapter(this, type, nextAnnotations))
                     }
                 }
             }
         }
     }
    
  3. 将工厂添加到 moshi 构建器

     val moshi = Moshi.Builder()
                 .add(SerializeNull.Companion.Factory)
                 .build()
    
  4. 用注释属性@SerializeNull(例如主持人)

     @JsonClass(generateAdapter = true)
     data class Event(
          val name: String,
          @SerializeNull val host: Host?,
          val venue: String?,
      )
    

一些测试

 @JsonClass(generateAdapter = true)
 data class Host(val firstName: String, val lastName: String?)

 @JsonClass(generateAdapter = true)
 data class Event(
     val name: String,
     @SerializeNull val host: Host?,
     val venue: String?,
 )


 @Test
 fun `everything is added to json if object has everything`() {
     val moshi = Moshi.Builder()
         .add(SerializeNull.Companion.Factory)
         .build()
     val jsonAdapter: JsonAdapter<Event> = moshi.adapter()
     val event = Event(
         name = "Birthday Party",
         host = Host(firstName = "Harsh", lastName = "Bhakta"),
         venue = "House"
     )
     val json = jsonAdapter.toJson(event)
     assertEquals("""{"name":"Birthday Party","host":{"firstName":"Harsh","lastName":"Bhakta"},"venue":"House"}""", json)
 }

 @Test
 fun `check host  is null in json since host is annotated with serializeNull and venue is excluded because it's not annotated`() {
     val moshi = Moshi.Builder()
         .add(SerializeNull.Companion.Factory)
         .build()
     val jsonAdapter: JsonAdapter<Event> = moshi.adapter()
     val event = Event(
         name = "Birthday Party",
         host = null,
         venue = null
     )
     val json = jsonAdapter.toJson(event)
     assertEquals("""{"name":"Birthday Party","host":null}""", json)
 }

 @Test
 fun `check nested property (host lastname) is not included if it's null because it's not annotated with SerializeNull`() {
     val moshi = Moshi.Builder()
         .add(SerializeNull.Companion.Factory)
         .build()
     val jsonAdapter: JsonAdapter<Event> = moshi.adapter()
     val event = Event(
         name = "Birthday Party",
         host = Host(firstName = "Harsh", lastName = null),
         venue = null
     )
     val json = jsonAdapter.toJson(event)
     assertEquals("""{"name":"Birthday Party","host":{"firstName":"Harsh"}}""", json)
 }

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用注释通过嵌套事件在 Moshi 中序列化 Null 的相关文章

  • Android 主机意图过滤器通配符

    是否可以在 android host 属性上使用通配符 就像是 android host site com android pathPattern android pathPrefix m android scheme http gt Or
  • Android KeyBoard.Key 禁用图标 预览特殊键?

    我通过实现 KeyboardView OnKeyboardActionListener 接口来自定义自己的软键盘 按下按键时 将显示预览弹出窗口 我的问题是如何禁用 SHIFT 和 DELETE 等特殊键的预览弹出窗口 我尝试将 andro
  • 使用 APDU 命令的有效 NFC 读取比特率是多少?

    我目前正在使用 Android IsoDep trancieve 函数发送和接收累计 1628 字节的数据 该函数分布在 35 个 APDU 命令 选择应用程序 身份验证 读取 中 字节计数包括返回的 MAC 校验和以及由 transcie
  • Android Studio - 错误:未捕获翻译错误:com.android.dx.cf.code.SimException:本地 0001:无效

    我刚刚使用 Android Studio 设置了一台新计算机 并从 bitbucket 导入了我的项目 问题是我现在在尝试构建项目时遇到此错误 信息 Gradle 任务 app clean app generateDebugSources
  • 如何将 EditText 传递给另一个活动?

    Intent intent new Intent this Name class intent putExtra key et getText toString startActivity intent Intent intent getI
  • 如何使用 adb 在设备上安装现有的 Android 应用程序?

    在开发过程中 我使用类似的东西 adb s 192 168 1 77 5555 uninstall com myApp app adb s 192 168 1 77 5555 install path to android debug ap
  • Google Firebase - 如何删除崩溃报告?

    我最终失明了吗 还是没有明显的方法可以通过 Google Firebase Web 控制台删除 Firebase 崩溃报告 我的 Android 应用程序已成功记录报告 但现在出现大量 开发崩溃 占用了我在控制台中的大部分视图 这使得找到实
  • 按钮未显示在屏幕上

    我创建了一个应用程序 其中显示带有图像和文本的列表视图 我在页面末尾添加按钮 但这没有显示在屏幕上 我是 Android 新手 我该如何解决这个问题 这是我的 UI XML 代码
  • Android中不同线程的数据库访问

    我有一个在 AsyncTasks 中从互联网下载数据的服务 它解析数据并将其存储在数据库中 该服务持续运行 当服务写入数据库时 活动会尝试从数据库中读取更改 我有一个数据库助手 有多种写入和读取方法 这会导致问题吗 可能尝试从两个不同的线程
  • 获取可以共享数据的应用程序列表

    此代码显示默认共享对话框 Intent sharingIntent new Intent Intent ACTION SEND sharingIntent setType text html sharingIntent putExtra a
  • Android Web Intent 问题

    G day 免责声明 我不是 Android 开发人员 我正在对我所描述的问题进行质量检查 我用来描述这个问题的技术术语可能是错误的 我正在测试一个 Android 应用程序 该应用程序在其清单中描述它可以使用 type 的地址处理 Web
  • window.onbeforeunload 在 Android Chrome 上不会触发 [alt.解决方案?]

    我开发了一个简单的聊天应用程序 我正在使用 window onbeforeunload当有人关闭选项卡 浏览器时 基本上是当用户离开房间时 通知其他用户 这是我的代码 scope onExit function scope chatstat
  • Integer.parseInt("0x1F60A") 以 NumberformatException 结束

    我尝试从数据库中获取长字符串内的表情符号代码 格式如下 0x1F60A 所以我可以访问代码 但它将是String 起初 我尝试通过执行以下操作来转换变量tv setText beforeEmo getEmijoByUnicode int e
  • jar 中的 apklib 有什么优点?

    我正在关注这个问题 https stackoverflow com questions 6059502 whats the difference between apklib and jar files但它并没有完全回答我的问题 jar 中
  • 删除Android所有语言中的字符串

    我有一个包含多个翻译的应用程序 我想删除一些字符串 我怎样才能重构并删除它们一次 例如在默认情况下strings xml文件并自动将删除传播到其他翻译的其他 strings xml 文件 您可以通过 Android Studio 中的 翻译
  • 使用嵌套的 hashmap 参数发送 volley 请求

    我正在使用 android volley 框架向我的服务器发送 jsonobject 请求 get 请求工作正常 现在我想发送一个带有请求参数的 post 请求 该请求参数是嵌套的 hashmap 我重写 getparams 方法 但它期望
  • 更改Android菜单的背景颜色[重复]

    这个问题在这里已经有答案了 我正在尝试将标准浅灰色更改为浅绿色 似乎没有一个简单的方法可以做到这一点 例如 通过 Android 主题 但我找到了一个解决方法 如本页所述 http tinyurl com 342dgn3 http tiny
  • 如何在Android中解析xml类型的HTTPResponse

    我有一个 Android 应用程序 我使用 POST 方法来获取响应 这是我的代码 HttpResponse httpResponse httpclient execute httppost HttpEntity resEntity htt
  • 如何以编程方式创建活动转换?

    我想以编程方式创建一个动画 以从触摸屏点启动具有缩放效果的活动 接下来我模拟缩放输入效果
  • 使用 Python 将对象列表转为 JSON

    我在转换时遇到问题Object实例到 JSON ob Object list name scaping myObj base url u number page for ob in list name json string json du

随机推荐

  • 命名空间 + 函数与类上的静态方法

    假设我已经或将要编写一组相关函数 假设它们与数学相关 从组织上来说 我应该 编写这些函数并将它们放入我的MyMath命名空间并通过引用它们MyMath XYZ 创建一个名为MyMath并使这些方法静态并引用类似的MyMath XYZ 为什么
  • iOS-示例中的协议和委托

    好吧 我正在寻找 但没有任何方法对我有用 以下代码基于许多教程和苹果文档 但我无法让它工作 有人可以帮忙吗 代码崩溃于 obj delegatee self 在 B h 类中 respondsToSelector 和 PerformSele
  • 尝试使用工作台将 postgresql 数据库迁移到 mysql 时出错

    我正在尝试按照本教程将 postgresql 数据库迁移到 mysql http mysqlworkbench org 2012 11 how to migrate postgresql databases to mysql using t
  • Healpy python-3..4 在 ubuntu-14.04 上的安装问题

    我是 ubuntu 新手 在 lenovo t410 上使用 ubuntu 14 04 和 python 3 4 为了安装 Healpy 我遵循了以下步骤 我已经使用安装了 python3 dev 包 sudo apt get instal
  • Visual Studio Code / powershell 命令历史记录向上键

    我可以通过什么方式在 Visual Studio Code 中记录之前输入的命令 例如 当我按下向上键时 我可以向上浏览之前的所有命令 如果可能的话 我想将这些记录到文件中 它们本地存储在哪里 我可以用节点之类的东西记录它吗 实际上 我自己
  • 在页面显示到屏幕之前删除 DOM 元素(在 Chrome 扩展中)

    我正在尝试创建一个扩展 该扩展将在页面显示到屏幕上之前删除某些页面元素 按 id 或类 我尝试在文档上使用事件侦听器 以 DOMContentLoaded 作为事件 但 javascript 似乎在页面显示给用户后执行 然后删除它 所以它不
  • 基于 Django 类的视图和表单集

    我有一个基于类的视图称为OrganizationsCreateView它包括附加到模型表单的表单集作为该表单的实例变量 当用户输入数据时 这可以正常工作 可以很好地创建一个新对象 当用户想要向表单集中添加其他行时 我有一个提交按钮 可以触发
  • iOS glGenerateMipmap 是同步的,还是可能是异步的?

    我正在开发一个在 OpenGL ES 中使用大纹理的 iPad 应用程序 当场景首次加载时 我在天花板上看到了几帧的大型黑色伪像 如下图所示 就好像更高级别的 mipmap 尚未填充 在后续帧中 天花板正确显示 当我开始使用 mipmapp
  • 如何使用 mongocxx c++ 驱动程序递归生成 Mongodb 文档?

    如何使用 mongocxx c 驱动程序递归生成 Mongodb 文档 1 我使用 mongocxx c 驱动程序 v 3 和 c 11 2 这是我的 main cpp 方法 它解析十六进制字符串并生成 mongocxx 代码 如下所示 控
  • 在 Trie 中插入值

    我在 SML 目录中找到了 Trie 的实现 signature DICT sig type key string concrete type type a entry key a concrete type type a dict abs
  • Android 无法初始化 Visualizer 引擎,错误:-4

    我有一个错误 public class VisualizerCapture extends Activity implements Visualizer OnDataCaptureListener private Visualizer mV
  • 玩 Scala 和线程安全

    该项目是使用编写的Play framework and Scala语言 我已经实施了compile time dependency 我按照 Play 中的这个例子进行操作 https github com playframework pla
  • 通过循环遍历另一个数组来填充新数组

    我正在做一些计算 根据用户输入 应进行计算并构建包含数据的表格 我的第一个数组 calcTable正在按预期工作 但是每一行代表一个月 在我的决赛表中 我想要一行代表一年 所以我目前正在尝试填充一个新数组 calcTableShow将保存这
  • Ada:如何解决“循环单元依赖”?

    假设我有两条记录 Person and Animal 每条记录都在一个单独的包中 包人 with animals use animals package persons is type person is record animalref
  • 仅将样式表应用于特定元素特征

    经过一番谷歌搜索后 我无法找到答案 所以这是我的问题 有没有办法指定应应用整个样式表的特定元素特征 例如 id 例如 如果我有一个像这样的 html 块 div div 有没有办法指定其中包含的规则 style css应该只应用于与 in
  • 安卓输入法连接错误

    我正在将我的 Android 客户端模拟器连接到服务器 Servlet 输出流工作正常 服务器正在打印从客户端发送的消息 服务器正在成功发送响应 但android输入连接是被动的 这里的错误显示在logcat中 showStatusIcon
  • 如何防止 IIS 默认站点 web.config 文件被虚拟目录继承?

    我在默认 IIS 站点的 web config 文件中有以下代码
  • 如何在 JavaScript 中将字符串的第一个字母变为大写?

    如果字符串是字母 如何将其第一个字符设为大写 但不更改任何其他字母的大小写 例如 this is a test This is a test the Eiffel Tower The Eiffel Tower index html inde
  • 如何在 Windows 8 Metro 应用程序中获取设备 ID

    如何获取Windows应用商店应用 Metro应用 中的唯一设备 我们可以使用 Windows System Profile HardwareIdentification GetPackageSpecificToken null Windo
  • 使用注释通过嵌套事件在 Moshi 中序列化 Null

    我正在尝试添加自定义注释 以便在调用时将模型中的特定值序列化为 nulltoJSON来自莫西的方法 我有一些基于此的工作response https stackoverflow com questions 52254876 moshi cu