java - 使用 Java 和 Ruby 实现 JSON 中的多态性或继承

标签 java ruby json inheritance single-table-inheritance

对于上下文,我们将大部分数据存储为 JSON 字符串。这与后端的 Hadoop 配合得很好,并且在前端的 Ruby 中也很容易处理。我的数据类型符合继承的自然模式。

为简单起见,假设我有一个 Pet 类和一个喂养宠物的进程 FeedPet。我还有一个进程WalkDog,它只适用于Dog,它是一种宠物。我的数据经过整理,因此我永远不必担心尝试遛狗以外的宠物。

我想做的是让 Pet 和 Dog 扩展 Pet,Dog 有一个额外的方法“getLeash()”,但我不知道如何将其映射到 JSON。

相反,我有一个带有物种数据 HashMap 的 Pet 类,因此 WalkDog 进程将调用 pet.getSpeciesData("leash") 而不是 dog.getLeash()。

我可以创建一个 Dog extends Pet,我可以使用 Jackson 库将其序列化为 JSON。 JSON 对象将有一个 leash 字段。但假设我想喂养所有的宠物。所有宠物都有一个 getFood() 方法。所以 FeedPet 进程将对象反序列化为 Pet。但这失去了皮带场。

WalkDog 进程可以执行此操作,因为它知道它的所有输入都将是 Dog,因此它可以将其作为 Dog 读取并作为 Dog 写回。

有什么方法可以将 java 对象序列化为 JSON 以便我可以保留它们的类型?我在想类似 Rails 单表继承的东西,但它必须是 JSON 库可以理解的东西。

最佳答案

为了让它工作,你必须在数据中嵌入一些对象类型信息(它只对反序列化有用)并且通常使用外部模式定义,否则就不需要(比如 xml 的 XML 模式;因为这基本上是一个通用的类型系统)。 这与 ORM 存在相同的问题:Hibernate 必须使用丑陋的变通方法(n+1 - 方式连接、“ super 表”或鉴别器字段)。

或者换一种说法:数据映射/绑定(bind)与对象序列化/反序列化并不完全相同(后者试图保留更多的对象身份)。

这里我假设你想要的基本上是这样的:

Pet pet = mapper.readValue(jsonString, Pet.class);
// (and possibly get an exception if Pet is an abstract class...)
Leash l = ((Dog) pet).getLeash();

如果不是这种情况,您可以简单地绑定(bind)到 Dog

Dog dog = mapper.readValue(jsonString, Dog.class);

所以无论如何:Jackson 项目有 feature request for doing just this ,这让你可以做(​​我认为)你想做的事。

但是,此解决方案主要适用于 Java,因为在 JSON 中没有传递对象类型信息的标准方法。对于 XML,这可以通过 XML Schema 定义的“xsi:type”属性来完成;它标识模式类型,然后映射到类(是的,相当复杂的方式,但它确实有效)。

更新:Jackson 1.5添加了对此的支持(即实现的 JACKSON-91 功能请求),因此它可用于生成类型标识符,以允许正确处理多态类型。它也应该适用于非 Java 系统,因为您可以完全配置如何包含类型信息的详细信息;并且不限于使用 Java 类名。

关于java - 使用 Java 和 Ruby 实现 JSON 中的多态性或继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/727681/

相关文章:

jquery - 如何从 json 数组中 foreach 唯一值

java - RecyclerView未从firebase数据库中获取数据

java - 在 Hibernate Criteria 中访问复合键

java - 提取字符串中的字符串

ruby-on-rails - ' rake ' "in order to" 'rake'

json - 将 JSON 元组解码为 Elm 元组

java - Spring集成消息历史记录

ruby-on-rails - Rails 依赖 : :destroy causes ArgumentError

ruby-on-rails - 我何时何地需要 Rails 应用程序中的文件?

android - 如何在Android上解析 "unit-test"json(JSONObject == "null")?