为 property = "type.id" 选择什么 @JsonTypeInfo.ID 进行反序列化,JsonTypeInfo.Id.CUSTOM?

2024-01-12

所以我的 JSON 看起来像这样:

{
    "ActivityDisplayModel" : {
        "name" : "lunch with friends",
        "startTime" : "12:00:00",
        "type" : {
            "id" : "MEAL",
            "description" : "Meal"
        },
        "complete" : false
    }
}

我正在努力寻找获得的方法@JsonTypeInfo不要因为我在其中包含类型参数而生气type目的。我以前在野外时就已经做到了这一点type是一个字符串,而不是一个对象本身,但为了以后的处理,我需要它作为一个对象。我知道以下方法不起作用,我猜有一种方法可以使用JsonTypeInfo.Id.CUSTOM http://fasterxml.github.io/jackson-annotations/javadoc/2.3.0/com/fasterxml/jackson/annotation/JsonTypeInfo.Id.html#CUSTOM,但是在互联网上查遍之后,没有出现 JSON 的完整示例。另外,如果这可以通过 objectMapper 设置实现,我会洗耳恭听。

/** 
 * My ActivityDisplayModel Abstract Class
 */
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type.id")
@JsonSubTypes({
@JsonSubTypes.Type(value = MealDisplayModel.class, name = "MEAL"),
@JsonSubTypes.Type(value = EntertainmentDisplayModel.class, name = "ENTERTAINMENT")
})
public abstract class ActivityDisplayModel { 
    ...

上面基本上是我想做的,但当然我有一个例外:

Could not read JSON: Could not resolve type id '{' into a subtype of  [simple type, class ... .ActivityDisplayModel]

对于这样一个简单的问题,只要在 JSON 中深入一层,谁会想到会这么麻烦呢?


我知道距最初的问题已经过去了 3 年,但仍然不支持点嵌套属性,也许这会对某人有所帮助。我最终创建了一个类NestedTypeResolver所以我们可以按预期使用点语法。只需添加@JsonTypeResolver(NestedTypeResolver.class)对于任何具有嵌套鉴别器的类,发布者的原始尝试都将起作用:

/** 
 * My ActivityDisplayModel Abstract Class
 */
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type.id")
  @JsonSubTypes({
  @JsonSubTypes.Type(value = MealDisplayModel.class, name = "MEAL"),
  @JsonSubTypes.Type(value = EntertainmentDisplayModel.class, name = "ENTERTAINMENT")
})
@JsonTypeResolver(NestedTypeResolver.class)
public abstract class ActivityDisplayModel {

嵌套类型解析器:

/**
 * Allows using nested "dot" dyntax for type discriminators. To use, annotate class with @JsonTypeResolver(NestedTypeResolver.class)
 */
public class NestedTypeResolver extends StdTypeResolverBuilder {
    @Override
    public TypeDeserializer buildTypeDeserializer(DeserializationConfig config, JavaType baseType,
            Collection<NamedType> subtypes) {
            //Copied this code from parent class, StdTypeResolverBuilder with same method name
            TypeIdResolver idRes = idResolver(config, baseType, subtypes, false, true);
            return new NestedTypeDeserializer(baseType, idRes, _typeProperty, _typeIdVisible,
                null, _includeAs);
    }
}

所有繁重的工作都在这里完成,嵌套类型反序列化器:

/**
 * Heavy work to support {@link NestedTypeResolver}
 */
public class NestedTypeDeserializer extends AsPropertyTypeDeserializer {

    private static final Logger LOGGER = LoggerFactory.getLogger(NestedTypeDeserializer.class);

    public NestedTypeDeserializer(JavaType bt,
            TypeIdResolver idRes, String typePropertyName, boolean typeIdVisible,
            JavaType defaultImpl) {
        super(bt, idRes, typePropertyName, typeIdVisible, defaultImpl);
    }

    public NestedTypeDeserializer(JavaType bt, TypeIdResolver idRes, String typePropertyName, boolean typeIdVisible,
            JavaType defaultImpl, JsonTypeInfo.As inclusion) {
        super(bt, idRes, typePropertyName, typeIdVisible, defaultImpl, inclusion);
    }

    public NestedTypeDeserializer(AsPropertyTypeDeserializer src, BeanProperty property) {
        super(src, property);
    }

    @Override
    public TypeDeserializer forProperty(BeanProperty prop) {
        return (prop == _property) ? this : new NestedTypeDeserializer(this, prop);
    }

    @Override
    public Object deserializeTypedFromObject(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode originalNode = p.readValueAsTree();
        JsonNode node = originalNode;
        //_typePropertyName is the dot separated value of "property" in @JsonTypeInfo
        LOGGER.debug("Searching for type discriminator [{}]...", _typePropertyName);
        for (String property : _typePropertyName.split("\\.")) { //traverse down any nested properties
            JsonNode nestedProp = node.get(property);
            if (nestedProp == null) {
                ctxt.reportWrongTokenException(p, JsonToken.FIELD_NAME,
                        "missing property '" + _typePropertyName + "' that is to contain type id  (for class "
                                + baseTypeName() + ")");
                return null;
            }
            node = nestedProp;
        }
        LOGGER.debug("Found [{}] with value [{}]", _typePropertyName, node.asText());
        JsonDeserializer<Object> deser = _findDeserializer(ctxt, "" + node.asText());
        //Since JsonParser is a forward-only operation and finding the "type" discriminator advanced the pointer, we need to reset it
        //Got clues from https://www.dilipkumarg.com/dynamic-polymorphic-type-handling-jackson/
        JsonParser jsonParser = new TreeTraversingParser(originalNode, p.getCodec());
        if (jsonParser.getCurrentToken() == null) {
            jsonParser.nextToken();
        }
        return deser.deserialize(jsonParser, ctxt);
    }
}

免责声明:我们已经在 J​​ackson 2.8.10 中使用了一个月,没有出现任何问题,但我们必须深入研究 Jackson 源代码才能完成它,所以 YMMV。 希望杰克逊有一天能够允许这种开箱即用的方式,这样我们就不需要这些解决方法。

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

为 property = "type.id" 选择什么 @JsonTypeInfo.ID 进行反序列化,JsonTypeInfo.Id.CUSTOM? 的相关文章

  • 如何解析比 Java 中 NumberFormat 更严格的数字?

    我正在验证表单中的用户输入 我解析输入NumberFormat http docs oracle com javase 7 docs api java text NumberFormat html 但它是邪恶的 几乎允许任何事情 有没有办法
  • Spring Batch 多线程

    我正在编写一个 Spring Batch 并希望在需要时对其进行扩展 我的 ApplicationContext 看起来像这样 Configuration EnableBatchProcessing EnableTransactionMan
  • 通过 JDBC 调用 Sybase 存储过程时结果集为空

    我正在调用一个通过 JDBC 返回多个结果集的 Sybase 存储过程 我需要获取一个特定的结果集 其中有一列名为 结果 这是我的代码 CallableStatement cs conn prepareCall sqlCall cs reg
  • 在 Java 和 C 中在运行时调用名为“string”的方法

    我们如何调用名称为的方法string在运行时 谁能告诉我如何在 Java 和 C 中做到这一点 在java中可以通过反射api来完成 看一下Class getMethod String methodName Class parameterT
  • Eclipse 说“更新 Android Developer Toolkit”

    我不知何故弄乱了我的 Eclipse 和 Android 设置 我不知道如何修复它 问题症状如下 在 首选项 gt Android 中 我尝试选择 android sdk linux 的位置 选择时出现错误 此 Android SDK 需要
  • 将图像缩略图上传到服务器,而不上传整个图像

    据我所知 我在这里问的是不可能的 但我想无论如何我都会问 以防我遗漏了什么 假设您想让用户上传 JPG 图像 并且这些图像被缩放为较小的图标 并且原始图像始终被丢弃并且不再需要 有没有什么方法可以在大多数现代浏览器中普遍使用 让用户选择硬盘
  • SwingWorker 在 Unsafe.park() 处挂起

    我有一个SwingWorker与后台服务器通信 然后更新JFrame 我正在调试我的应用程序并注意到即使在SwingWorker完成了它的工作 它的线程仍然存在 它挂在Unsafe park java lang Object 这是一个本机方
  • Maven:缺少工件 org.springframework:spring:jar:4.2.6

    我在 SpringToolSuite 中有一个动态 Web 项目 它被转换为 Maven 项目 我遇到问题 缺少工件 org springframework spring jar 4 2 6 我已经尝试清理 重建和运行该项目 它给 读取文件
  • toJSON() 和 JSON.Stringify() 之间的区别

    如果您需要读取或克隆模型的所有数据属性 请使用其 toJSON 方法 此方法返回属性的副本作为 对象 尽管有其名称 但不是 JSON 字符串 当 JSON stringify 为 使用 toJSON 方法传递一个对象 它将返回的字符串化 t
  • 为什么我无法解开根节点并反序列化对象数组?

    为什么我无法通过展开根节点来反序列化对象数组 import java io IOException import java util Arrays import java util List import org codehaus jack
  • Maven:如何获取捆绑在包中的 .so 库

    我有一个带有 jar 和 so 文件的第三方库 我配置了 pom xml 如下
  • 如何更改tomcat jmx密码的文件权限

    我正在尝试保护 Windows 平台上托管的本地 tomcat 实例上的 JMX 访问 我已经创建了访问权限和密码文件 并使用以下 VM 参数插入这些文件 Dcom sun management jmxremote password fil
  • 使用 Spring 注入 Google Guava Hashmultimap

    是否可以提供一个创建示例Multimap
  • 摆动刷新周期

    我试图了解何时使用重新验证 重绘 打包 令人惊讶的是 我没有找到详细的底层文档 请随意链接 到目前为止我已经明白这都是 RepaintManager 的责任 油漆 重新油漆指的是脏 干净的东西 pack validate revalidat
  • 在 jFrame 中启用右键单击

    嘿 我正在寻找如何使用 NetBeans 在 jFrame 中启用 仅且仅 右键单击并显示弹出菜单 使用我的代码 private void formMouseClicked java awt event MouseEvent evt pop
  • 为什么 Libgdx 的 Table 不接受缩放操作?

    我在 libgdx 库中使用 scene2d 在游戏中创建一些 UI 我使用了一个表格 我想在用户触摸时采取一些缩放操作以使按钮触摸有意义 当我使用任何其他 Actor 类型 例如 Group 并为其提供缩放操作时 它可以工作 但不能工作表
  • LinkedBlockingQueue 抛出 InterruptedException

    我有这段代码 ALinkedBlockingQueue应该只抛出一个Exception如果在等待添加到队列时被中断 但这个队列是无限的 所以它应该尽快添加 为什么我的关闭方法会抛出一个InterruptedException private
  • 使用 JPA 和 Hibernate 时 DISTINCT 如何工作

    DISTINCT 在 JPA 中使用什么列 是否可以更改它 以下是使用 DISTINCT 的 JPA 查询示例 select DISTINCT c from Customer c 这没有多大意义 不同的列是基于哪一列 它是否在实体上指定为注
  • 如何使用 JRE 部署 JavaFX 11 桌面应用程序

    我有一个 JavaFX JDK 8 桌面业务应用程序 它使用 Java Web Start 进行部署 用户安装了 Java 8 只需访问 URL 我的 AWS Linux 服务器上的公共 URL 即可下载 启动应用程序 使用 Web Sta
  • 如何获取 EC2 实例的 CloudWatch 指标数据

    我想获取我的 EC2 实例的 Cloudmetrics 数据 以便我可以使用这些数据绘制图表并将其显示在我的 Android 设备上 我怎么做 有相同的示例程序或教程吗 提前致谢 这就是我正在做的 private static void f

随机推荐

  • 两个日期之间不同年份的列表

    我想检索两个日期之间不同年份的列表 例如 从25 12 2006 to 14 11 2013 结果应如下所示 2006 2007 2008 2009 2010 2011 2012 2013 这在 SQL Server 中可能吗 像这样的约会
  • 如何登录 Fabrics 发送长消息

    我正在尝试在 Fabrics 系统 Android 上编写长文本日志消息 如下所示 Answers getInstance logCustom new CustomEvent Request requestUrl nResponse jso
  • iPhone开发

    我对 iPhone 开发非常感兴趣 以及如何开始 iPhone 开发 我对 C 没有基本的了解 但我有编程知识和概念 iPhone 开发中心 http developer apple com iphone index action是你的起点
  • 如何使用基于类的addEventListener检索当前元素?

    我正在使用一个函数来检索接收事件的当前元素 在本例中为单击 但我想从 HTML 脚本中删除该函数并使用event listener做同样的事情 但是我正在使用一个类来瞄准元素 如果我只有一个元素 那就很容易了 但事实并非如此 我的第一个想法
  • 在 MVC4 中显示错误,我必须实现一些接口,但我已经完成了

    我正在尝试创建自己的过滤器属性以支持多语言 这个想法很简单 URL 代表语言 http host ext en rest of the url 将以英语打开 并且 http host ext hy rest of the url 将以亚美尼
  • PhpStorm 中的差异

    如何将当前项目中的文档与不属于该项目的文档进行比较 如何使用 phpStorm 比较计算机上的两个任意文件 目前 我发现比较项目文件与非项目文件的最简单方法是将外部文件复制到剪贴板 然后单击 查看 gt 与剪贴板比较
  • PHP 将两个时间变量相加

    在我的 PHP 应用程序中 我想计算两个时间变量的总和 我正在寻找类似这个例子的东西 time1 15 20 00 time2 00 30 00 time time1 time2 如果你期望的答案是15 50 00你想使用strtotime
  • 执行 git reset --hard HEAD^ 后恢复添加/暂存的文件?

    我添加了一个新文件F1并对另一个文件 F2 进行了更改 但随后做了git reset hard HEAD 并且我丢失了对文件的所有更改 有没有some怎么样 我可以把它们找回来吗 我确实在这里看过一个相关问题 如何撤消 git reset
  • 更改函数中的每个 for 循环,以便在每次失败的迭代后自动执行错误处理

    这个问题源于捕获生成器内的错误并随后继续 https stackoverflow com questions 13645112 catch errors within generator and continue afterwards 我有
  • 使用 4 mb 查找不在 40 亿列表中的整数。但 4 MB 还不够[重复]

    这个问题在这里已经有答案了 给定一个包含 40 亿个整数的列表 找到一个不在列表中的整数 使用 4MB 内存 采访是用Java进行的 我的解决方案是使用 BitSet 然而根据我的计算 4 MB 内存中没有足够的位 c 4 MB 4096
  • 标题文本垂直居中

    我希望增加 jquery 移动应用程序标题的大小 当我这样做时 我需要将标题居中 我发现我可以添加一行 line height 30px 到CSS 但这还远远不够 我想一定有更好的方法来做到这一点
  • getSystemService(Context.NSD_SERVICE) 冻结 5.0 模拟器

    尝试执行以下行 NsdManager Mgr NsdManager Ctxt getSystemService Context NSD SERVICE 在 Android 5 0 模拟器 ARMv7a 在 Win64 上 中 模拟器会冻结
  • const_cast 的行为

    我正在阅读有关 C 中的 const cast 运算符的内容 1 我无法理解的第一件奇怪的事情是 const cast 运算符语法 即 const cast 表达式 gt 我对这种语法的理解是 它有助于摆脱常量性expressionof t
  • 这个shell测试达到什么目的

    我有一个非常简单的问题 我无法回答 在 shell 中 这个命令会做什么 test d VIRTUAL ENV virtualenv VIRTUAL ENV 它似乎测试 virtualenv 目录是否存在 但我不明白 if 会如何处理该信息
  • 快速或简洁地确定基于行的数据集合中每列的最长字符串

    从我上次查询的结果 https stackoverflow com questions 2760168 can i set auto width on an open xml sdk generated spreadsheet withou
  • 为什么实现 IObjectSafety 没有带来什么改变?

    我们有一个 activex 对象 它实现了 IObjectSafety 以表明它对于脚本编写是安全的 它从受信任的站点安装 但我们仍然收到 IE 投诉 称该页面上的控件对于脚本编写不安全 运行我们的 activex 的站点管理员不愿意启用未
  • HQL 查询 id 对/元组

    我正在尝试使用 HQL 查询两个域之间新创建的关系 所以我想做类似的事情 select x id y id from Author as x join x books as y where x id y id not in 1 2 3 4
  • 通过连接查询大型数据集(15+ 百万行)

    我正在尝试连接两个表 products and products markets While products记录不足一百万条 product markets接近2000万条记录 数据已更改 因此架构创建表中可能存在一两个拼写错误 CREA
  • Javascript 日期时间字符串到 Date 对象

    我正在调试一个小型应用程序 其某些功能只能在 Chrome 中运行 问题在于日期选择器 您在其中选择日期和时间 然后日期选择器将其连接到日期时间字符串中 无论如何 字符串看起来像这样 2012 10 20 00 00 然而 现在使用它的 j
  • 为 property = "type.id" 选择什么 @JsonTypeInfo.ID 进行反序列化,JsonTypeInfo.Id.CUSTOM?

    所以我的 JSON 看起来像这样 ActivityDisplayModel name lunch with friends startTime 12 00 00 type id MEAL description Meal complete