Jackson Scala JSON 反序列化为案例类

2023-12-01

我有一个 JSON,其形式如下:

{
"inventory": [
           {
        "productType": "someProduct1",
        "details": {
            "productId": "Some_id",
            "description": "some description"
        }
        },
 {
        "productType": "someProduct2",
        "details": {
            "productId": "Some_id",
            "description":{"someKey":"somevalue"}
        }
    }
]
}

我希望上面的 json 反序列化的案例类如下所示:

case class Inventory(products:List[Product])
case class Product(productType:String,details:ProductDetails)
abstract class ProductDetails
case class ProductDetailsSimple(productId:String,description:String) extends ProductDetails
case class ProductDetailsComplex(productId:String,description:Map[String,String]) extends ProductDetails

我在用Jackson-scala 模块反序列化上述 JSON 字符串,如下所示:

 val mapper = new ObjectMapper() with ScalaObjectMapper
 mapper.registerModule(DefaultScalaModule)
 mapper.readValue(jsonBody, classOf[Inventory])

我得到的错误如下: “意外的标记 (END_OBJECT),预期的 FIELD_NAME:缺少属性 '@details',该属性将包含类型 id(对于 ProductDetails 类)\n,位于 [来源:java.io.StringReader@12dfbabd;行:9,列:5]”

我已经经历过Jackson 关于多态反序列化的文档并尝试了上述组合,但没有成功。 我想了解我在这里做错了什么,需要针对使用杰克逊模块的反序列化进行纠正。


我认为这里有几个单独的问题需要解决,因此我列出了三种单独的方法。

TL;DR

要么正确使用 Jackson 多态性,要么根据您的情况,采用更简单的方法并消除对多态性的需要。看我的github上的代码.

1. 自定义解串器

您的 JSON 格式为:

{ inventory:
   [ { productType: 'someProduct1',
       details:
        { productId: 'Some_id',
          description: 'some description' } },
     { productType: 'someProduct2',
       details:
        { productId: 'Some_id',
          description: { someKey: 'somevalue' } 
        }
     } 
   ]
}

productType在我看来,这是错误的,但如果这种格式是严格要求,那么您可以编写自己的反序列化器来查看productType字段并实例化不同的具体类。

我认为这不是最好的解决方案,所以我没有编写示例代码,但我喜欢Joda 日期时间包作为自定义序列化/反序列化的参考

2. 杰克逊多态性

你们已经分开了Product from ProductDetails带有类型字段:

case class Product(productType:String,details:ProductDetails)

abstract class ProductDetails

我认为您已经混淆了 Jackson 的多态数据类型处理的工作原理,并因此使您的类设计变得复杂。

也许您的业务规则要求产品具有“类型”,在这种情况下,我会将其命名为“种类”或其他一些非代码标签,并将其放入您所说的内容中ProductDetails.

但是,如果“类型”被包含在试图使类型多态性发挥作用的过程中,那么它就不是正确的方法。

我将以下内容作为 Scala 中 Jackson 多态性的工作示例:

/**
 * The types here are close to the original question types but use 
 * Jackson annotations to mark the polymorphic JSON treatment.
 */

import scala.Array
import com.fasterxml.jackson.annotation.JsonSubTypes.Type
import com.fasterxml.jackson.annotation.{JsonSubTypes, JsonTypeInfo}

@JsonTypeInfo(
  use = JsonTypeInfo.Id.NAME,
  include = JsonTypeInfo.As.PROPERTY,
  property = "type")
@JsonSubTypes(Array(
  new Type(value = classOf[ProductDetailsSimple], name = "simple"),
  new Type(value = classOf[ProductDetailsComplex], name = "complex")
))
abstract class Product

case class ProductDetailsSimple(productId: String, description: String) extends Product

case class ProductDetailsComplex(productId: String, description: Map[String, String]) extends Product

case class PolymorphicInventory(products: List[Product])

请注意,我删除了Product vs ProductDetails的区别,所以Inventory现在只是作为一个列表Product。我留下了名字ProductDetailsSimple and ProductDetailsComplex虽然我认为他们应该重新命名。

用法示例:

val inv = PolymorphicInventory(
  List(
    ProductDetailsSimple(productId="Some_id", description="some description"),
    ProductDetailsComplex(productId="Some_id", description=Map("someKey" -> "somevalue"))
  )
)

val s = jsonMapper.writerWithDefaultPrettyPrinter().writeValueAsString(inv)
println("Polymorphic Inventory as JSON: "+s)

Output:

Polymorphic Inventory as JSON: {
  "products" : [ {
    "type" : "simple",
    "productId" : "Some_id",
    "description" : "some description"
  }, {
    "type" : "complex",
    "productId" : "Some_id",
    "description" : {
      "someKey" : "somevalue"
    }
  } ]
}

3.去除多态性

我建议在这种情况下根本不需要多态性,并且错误在于尝试将“描述”制作为单个字符串或键/值映射,而它们实际上是具有不同意图的字段。

也许涉及到数据遗留问题(在这种情况下请参阅自定义 deser 建议),但如果数据在您的控制范围内,我投票支持“变得更简单”:

case class Product(productId: String,
                   description: String="",
                   attributes: Map[String, String]=Map.empty)

case class PlainInventory(products: List[Product])

我使用起来更“scala-rific”Option表示缺少值,因此:

case class Product(productId: String,
                   description: Option[String]=None,
                   attributes: Option[Map[String, String]]=None)

用法示例:

val inv = PlainInventory(
  List(
    Product(productId="Some_id", description=Some("some description")),
    Product(productId="Some_id", attributes=Some(Map("someKey" -> "somevalue")))
  )
)

val s = jsonMapper.writerWithDefaultPrettyPrinter().writeValueAsString(inv)
println("Plain Inventory as JSON: "+s)

Output:

Plain Inventory as JSON: {
  "products" : [ {
    "productId" : "Some_id",
    "description" : "some description"
  }, {
    "productId" : "Some_id",
    "attributes" : {
      "someKey" : "somevalue"
    }
  } ]
}

工作最少的代码github.

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

Jackson Scala JSON 反序列化为案例类 的相关文章

  • 在 Scala 中实现不区分大小写比较的字符串类

    我有许多带有不区分大小写的字段的类 我想将这些类的实例放入 HashMap 中 并通过不区分大小写的字符串查找它们 我不是每次想通过字符串索引实例或通过字符串查找实例时都使用 toLowerCase 而是尝试将此逻辑封装在 CaseInse
  • JSON字符串转JS对象

    我正在使用 JS 对象通过 Google 可视化创建图表 我正在尝试设计数据源 首先 我在客户端创建了一个 JS 对象 var JSONObject cols id date label Date type date id soldpenc
  • 如何使用Gson将JSONArray转换为List?

    在我的 Android 项目中 我试图将收到的 JSONArray 转换为列表 在 的帮助下这个答案 https stackoverflow com questions 8371274 how to parse json array in
  • IE8 上 json 解析失败

    json gt 返回的响应 msg div p Unfortunately we were unable to process your application p br Please upload a CV br div status e
  • 在 scalaz 中免费实施

    Haskell 中的免费实现是 data Free f a Pure a Free f Free f a 而 Scalaz 中的实现是 sealed abstract class Free S A private case class Re
  • 如何在 ECMAScript 6 中导入 JSON 文件?

    如何访问 ECMAScript 6 中的 JSON 文件 以下不起作用 import config from config json 如果我尝试导入 JavaScript 文件 这可以正常工作 https www stefanjudis c
  • 有没有某种方法可以为嵌套在 Jackson 的可选类型中的类型指定自定义反序列化器?

    我有一些类型需要用它们自己的特殊反序列化器和序列化器来处理 但是当类型嵌套在可选中时 如何指示 Jackson 使用它们 我正在使用 JDK8Module 它适用于任何不需要任何特殊处理的类型 当 JsonDeserialize和 Json
  • postgresql to_json() 函数转义所有双引号字符

    我编写了一个 plpgsql 脚本 它在字符串中生成一个 json 对象数组 但是在我使用 to json 方法将带有该字符串的变量传递给它之后 它返回一个带双引号的结果 并且每个双引号字符都被转义 但我需要原样的字符串 jsonResul
  • Scala 中 Null/Nothing/Unit 的用法

    我刚刚读过 http oldfashionedsoftware com 2008 08 20 a post about nothing http oldfashionedsoftware com 2008 08 20 a post abou
  • 使用 ActiveModel::Serializers 包含两个父 json 数组

    我正在尝试发送如下所示的前端应用程序 json facilities id 5 name happy days ranch location address 1424 Pastoral Lane zipcode 25245 instruct
  • 为 DocumentDb 设置自定义 json 转换器

    我正在使用类型化 DocumentQuery 从 Azure DocumentDb 集合中读取文档 from f in client CreateDocumentQuery
  • 在 Scala 中创建 Java 对象

    我有一个 Java 类 Listings 我在 Java MapReduce 作业中使用它 如下所示 public void map Object key Text value Context context throws IOExcept
  • 将类型信息传递给 Scala 中的函数

    我有对 json 对象执行一些常见操作的代码 即提取 所以我想创建一个通用函数 它接受哪个类的类型参数 代码如下所示 def getMessageType T json JValue Either GenericError T try Ri
  • JSON 编码和大引号

    我在 PHP 5 的本机实现中遇到了一个有趣的行为json encode 显然 当将对象序列化为 json 字符串时 编码器将清空包含 卷曲 引号的字符串的任何属性 这种类型可能会在启用自动转换的情况下从 MS Word 文档中复制粘贴 这
  • Scalaz 状态 monad 示例

    我还没有看到很多 scalaz 状态单子的例子 有这个例子 http scalaz github com scalaz scalaz 2 9 1 6 0 2 doc sxr scalaz example ExampleState scala
  • 使用流分析将自定义事件维度从 Application Insights 导出到 SQL

    我正在按照示例演练进行操作使用流分析从 Application Insights 导出到 SQL https azure microsoft com en us documentation articles app insights cod
  • HttpResponseMessage 的内容为 JSON

    我有一个 ASP NET MVC WEB API 由于多种原因 由于没有授权而重定向 我不能只使用一个简单的对象并在我的控制器方法中返回它 因此我需要 HttpResponseMessage 类来允许我重定向 目前我正在这样做 var re
  • 用于验证一个参数的多种类型和值的 json 架构

    请在这件事上给予我帮助 我尝试编写一个 json 模式来验证以下对象 json 对象 param value 可能的值 all 任意整数的数组 所以它是一个简单的 json 对象 其中包含一个变量 可以是字符串 all 也可以是任何整数数组
  • Scala Stream 按需要调用(惰性)与按名称调用

    所以我知道按需要呼叫只是按名称呼叫的记忆版本 在 Martin Odersky 在 Coursera 上的 FP 课程中 第 7 3 讲 惰性评估 中 他提到如果 Streams 是使用按名称调用来实现的 那么它可能会导致计算复杂性的激增
  • 如何更改 SBT 命令内的设置?

    我想要一个命令publish snapshot这将运行publish修改后的任务version设置 该设置将在执行命令时计算 我想出了如何获取当前值version内部命令 以及Project runTask task scope 似乎是调用

随机推荐

  • Python lambda 不接受元组参数[重复]

    这个问题在这里已经有答案了 我在两台 PC Linux 和 Windows 上运行带有 PyDev v2 6 插件的 Eclipse SDK v3 6 我想传递一个元组作为参数 例如 foo lambda x y y x print foo
  • Fancybox 导致 IE 加载速度缓慢?

    我正在使用 Fancybox v 1 3 4 在 iframe 中显示视频这一页 Fancybox 和视频显示良好 但问题是 自从添加代码后 我在 IE7 8 中加载网站时遇到了巨大的停顿 类似于这个问题 页面加载后 UI 冻结了 4 5
  • 从故障转储中获取 GDI 句柄计数的命令

    我有一个故障转储 我怀疑 GDI 泄漏是导致崩溃的原因 从完整的故障转储中是否可以找出我的进程崩溃时使用的 GDI 句柄的数量 我创建了一个 Windbg 脚本来转储 GDI 句柄表中的所有 GDI 句柄 看https aloiskraus
  • 构建 Logistic 回归模型时出现“检测到完美分离,结果不可用”

    作为我作业的一部分 我正在构建逻辑回归模型 但在构建模型时出现错误 检测到完美分离 结果不可用 X train year amt spnt rank 1 1 723034 0 418500 0 272727 2 0 716660 2 088
  • QTimer::timeout 没有触发

    我正在尝试创建一个在我的 Singleton 工作线程中每 n 秒触发一次的事件 信号 槽连接 信号是 QTimer 超时 槽是调用另一个 Singleton 类的 lambda 函数 无法正常工作 连接调用成功 计时器处于活动状态 并且我
  • 两列布局,左侧流体,右侧填充其余宽度

    我需要类似的东西this and this 但是我希望右列不是固定大小 而是可变大小 是否可以 some text stretch to fill the remaining space lt viewport 这是float解决方案 您可
  • Java 构造函数中的“this”

    嗯 这是一个非常基本的问题 我从来没有用java编写过代码 但我正在为朋友编写一个类 有类似的东西 class myClass private string name public string getName return this na
  • 如何通过php找到给定的十进制值的位数?

    我对php不太熟悉 但我知道我们可以通过php找到给定数字的位值 例如 如果输入为 23 56 则应回显 2 十 3 个 5 百分之一 6 千分之一 任何想法将不胜感激 请帮忙 Try str 23 56 strdiv explode st
  • Spark RDD:如何最有效地计算统计数据?

    假设存在类似于以下的元组 RDD key1 1 key3 9 key2 3 key1 4 key1 5 key3 2 key2 7 计算每个键对应的统计信息的最有效 并且理想情况下是分布式 的方法是什么 目前 我特别希望计算标准差 方差 据
  • 二维数组与一维数组的性能

    在 C 中 m n 二维数组与长度为 m n 的一维数组 对于 m 和 n 的较大值 之间在时间和空间上是否存在差异 使用一维数组访问元素会更快吗 在 C 中 二维数组只是一维数组的简洁索引方案 就像一维数组一样 二维数组分配单个连续内存块
  • 无法在 webview 上加载地理位置

    我想将地理位置加载到 android 2 1 上的 webview 中 地理定位在我的浏览器上运行良好 但在 webview 上却失败了 public class WebPageLoader extends Activity impleme
  • Pyspark:pandas_udf、grouped_agg 的多个参数

    我正在尝试应用带有两个参数的 pandas udf 但我有这个错误 首先我尝试使用一个参数 没问题 from pyspark sql functions import pandas udf PandasUDFType from pyspar
  • re.sub 中的 python 正则表达式条件 - 如何?

    是否可以使用python的正则表达式条件re sub 我尝试了多种变体但没有运气 这就是我所拥有的 import re match anything
  • Spring - 自动装配通用接口的通用实现

    我有一个小问题 这可能是微不足道的 但我以前从未遇到过 我有通用接口和它的通用实现 我想自动装配它 但发生了错误 详细信息如下 界面 Service public interface Serializing
  • Node-Webkit (nwjs) 节点远程用法

    我想知道如果我想从服务器运行应用程序的一些逻辑 功能 是否有人可以给我一个关于 节点远程 如何工作的示例 就像 我不知道在 package json 添加 node remote hostip 后该怎么做 我的服务器应该提供什么 js 文件
  • Scala:确保大括号平衡

    我正在运行代码来平衡语句中的括号 我认为我已经得到了正确的结果 但它在一个特定的陈述上失败了 我需要理解为什么 这是测试 特别是它失败了 除了编码之外 我认为我需要修复算法 有什么指示吗 def balance chars List Cha
  • 将“Cookie”放入“CookieJar”中

    我正在使用PythonRequests库来发出 HTTP 请求 我从服务器获取文本形式的 cookie 我怎样才能把它变成CookieJar里面有饼干吗 旧版本的Requests图书馆 0 14 2和更老的 当你经过时 把新的饼干放进罐子里
  • 如何使用 Jquery 或 Javascript 更改 .CSS 文件?

    我想知道是否可以使用 Jquery 或 javascript 对 css 文件进行更改 我知道 我可以动态地将 css 属性 或类 添加到 DOM 元素 但我不想要那样 我想在 css 文件中进行更改以自定义 css 文件的 css 类 请
  • 如何为 EF Code First 配置 ProviderManifestToken

    我有一个使用 EF 代码优先的 asp net MVC3 项目 对于我的单元测试 我一直使用 SQL Server CE 4 0 和 SQL Server 2008 Express 两者都与 EF 完美配合 按预期生成我的数据库 但是 当我
  • Jackson Scala JSON 反序列化为案例类

    我有一个 JSON 其形式如下 inventory productType someProduct1 details productId Some id description some description productType so