JAXB 继承冲突 - 重新注释子类

2024-05-29

目前我的项目中有这样的环境:

public abstract class Foo {

   private List<Thing> things;

   public List<Thing> getThings() { return this.things; }
}

public abstract class Bar extends Foo {


   @XmlElements({@XmlElement(name = "first", type = First.class)})
   public List<Thing> getThings() { return super.getThings(); }

}

public class Bobar extends Bar {

   @XmlElements({@XmlElement(name = "second", type = Second.class)})
   public List<Thing> getThings() { return super.getThings(); }

}

对于以下 XML 文档

<bobar>
   <first>blablabla</first>
   <second>blublublu</second>
</bobar>

当我做

context = JAXBContext.newInstance("the.package.structure");
unmarshaller = context.createUnmarshaller();
Bar object = (Bar) unmarshaller.unmarshal("path-to-xml-document");

The Bar object集合中只有 1 个元素,而不是 2 个。First当我尝试做时,元素完全丢失了object.getThings(),它的大小为 1,集合中唯一的对象是Second。有人可以帮助我如何才能获得集合中的两个对象吗?如果这是不可能的,我怎样才能实现类似的目标?

我这样做的原因是(在我的项目逻辑中)每个Bobars 物品收藏有一个First在它的收藏中,但不是每一个Bar has a Second在其收藏中,以及Foo是一个泛型类。

Edit:

当我更改 XML 文档中的顺序时,输出会有所不同。

<bobar>
   <second>blablabla</second>
   <first>blublublu</first>
</bobar>

在这种情况下,我只得到一个实例First在集合中,以及Second丢失了。进一步改变场景,我得到了有趣的结果:

public abstract class Foo {

   private List<Thing> things;

   public List<Thing> getThings() { return this.things; }
}

public abstract class Bar extends Foo {


   @XmlElements({@XmlElement(name = "first", type = First.class), @XmlElement(name = "third, type = Third.class)})
   public List<Thing> getThings() { return super.getThings(); }

}

public class Bobar extends Bar {

   @XmlElements({@XmlElement(name = "second", type = Second.class)})
   public List<Thing> getThings() { return super.getThings(); }

}

If I do

<bobar>
   <third>bliblibli</third>
   <second>blablabla</second>
   <first>blublublu</first>
</bobar>

理论上,我认为这不应该针对由此生成的 XML 架构进行验证,因为这里的顺序不正确。但除此之外,在这种情况下,我得到Second and First, the Third丢失了。


不可能在超类型上注释属性,并尝试将子尝试增量添加到该映射中。以下是您可以支持您所追求的所有用例的一种方法。需要注意的一件事是对象层次结构中的所有级别都支持同一组元素。您需要使用外部验证方法来限制所需的值。

If Thing是一个类而不是一个接口,并且First and Second extend Thing那么你可能有兴趣使用@XmlElementRef代替@XmlElements (see: http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-substitution.html http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-substitution.html)。它将为您提供更大的灵活性,但需要进行一些验证(很难限制有效值的集合)。

Bar

我们将注释Bar with @XmlTransient这样 JAXB 实现就不会处理它。

package forum11698160;

import java.util.List;

import javax.xml.bind.annotation.XmlTransient;

@XmlTransient
public abstract class Bar extends Foo {

    public List<Thing> getThings() {
        return super.getThings();
    }

}

Bobar

@XmlElementRef对应于 XML 模式中替换组的概念。与属性匹配的值将基于@XmlRootElement声明。

package forum11698160;

import java.util.List;
import javax.xml.bind.annotation.*;

@XmlRootElement
public class Bobar extends Bar {

    @XmlElementRef
    public List<Thing> getThings() {
        return super.getThings();
    }

}

Thing

由于 JAXB 实现无法使用反射来查找某个类型的所有子类,因此我们可以使用@XmlSeeAlso注释来帮忙。如果您不使用此注释,那么您将需要在引导时包含所有子类型JAXBContext.

package forum11698160;

import javax.xml.bind.annotation.XmlSeeAlso;

@XmlSeeAlso({First.class, Second.class})
public class Thing {

}

First

我们需要注释First with @XmlRootElement:

package forum11698160;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class First extends Thing {

}

Second

Second还需要注释@XmlRootElement:

package forum11698160;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Second extends Thing {

}

Demo

package forum11698160;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Bobar.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum11698160/input.xml");
        Bobar bobar =  (Bobar) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(bobar, System.out);
    }

}

输入.xml/输出

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bobar>
    <first/>
    <second/>
</bobar>

其他文件

以下是运行此示例所需的其他文件:

Foo

package forum11698160;

import java.util.*;

public abstract class Foo {

    private List<Thing> things = new ArrayList<Thing>();

    public List<Thing> getThings() {
        return this.things;
    }

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

JAXB 继承冲突 - 重新注释子类 的相关文章

随机推荐

  • 垂直 ViewPager 中的动画

    我需要垂直制作这个动画ViewPager https www youtube com watch v wuE 4jjnp3g https www youtube com watch v wuE 4jjnp3g 这是我到目前为止所尝试的 vi
  • 无法在 Powershell 中运行 R.exe

    我经常发现在命令行 Windows 上运行 R 更有用 然而 当我在 Powershell 中尝试时 我往往会遇到问题 但这可以通过第一次运行轻松克服cmd然后就可以了 这是我执行此操作时遇到的错误R CMD BATCH Invoke Hi
  • 检测 iPhone 屏幕是否打开/关闭

    有没有办法检测 iPhone 的屏幕是打开还是关闭 例如 当按下手机的屏幕锁定按钮时 我一直在使用 void applicationWillResignActive UIApplication application 为此类事件做准备 在大
  • Kivy - 文本换行工作错误

    我正在尝试在 Kivy 1 8 0 应用程序中换行文本 当没有太多文字时 一切正常 但如果文本很长并且窗口不是很大 它只是剪切文本 这是示例代码 vbox BoxLayout orientation vertical size hint y
  • Python 2.7 将比特币私钥转换为 WIF 私钥

    作为一名编码新手 我刚刚完成了教程 教程是这样的 https www youtube com watch v tX XokHf nI https www youtube com watch v tX XokHf nI 我想用 1 个易于阅读
  • 如何使用 jQuery 选择第一个块级父级?

    考虑以下标记 div h1 span span lorem ipsum span span h1 div 如何找到块级别的 span 3 的第一个父级 即具有display block 使用 jQuery 在这种情况下 那就是h1 1 3
  • boto3 资源(例如 DynamoDB.Table)的类型注释

    The boto3库提供了几种返回资源的工厂方法 例如 dynamo boto3 resource dynamodb Table os environ DYNAMODB TABLE 我想注释这些资源 以便我可以获得更好的类型检查和完成 但我
  • Java 小程序在 Mac 上闪烁

    这个问题很奇怪 问题并非在每个平台上都会发生 我在使用 MacOSX 的 Google Chrome 中出现了这种情况 但在 Safari 中却没有出现这种情况 对于使用 Windows 的朋友来说 在 Google Chrome 上运行得
  • 尚未为此带有 SQL Server 的 DbContext .NET Core 配置数据库提供程序

    我一直用这个把头撞在墙上 并且一直在谷歌上搜索无济于事 我刚刚开始一个新的 ASP NET Core MVC 项目 我已将这两个包安装 更新为 2 2 0 Microsoft EntityFrameworkCore SqlServer Mi
  • LINQ 对特定属性的 Distinct()

    我正在玩 LINQ 来了解它 但我不知道如何使用Distinct https learn microsoft com en us dotnet api system linq enumerable distinct当我没有一个简单的列表时
  • 如何围绕指定的锚点以 2D 方式旋转容器小部件?

    我想对容器小部件 包含一些其他小部件 执行非常简单的 2D 旋转 该小部件将围绕中心的单个固定点旋转 不会变形 我尝试使用transform财产与Matrix4 rotationZ 这有点起作用 但锚点在top left角落 不在cente
  • 使用 Symfony 时如何处理连接表中的附加列?

    假设我的 Symfony2 包中有两个实体 User and Group 通过多对多关系关联 USER USER GROUP REL GROUP id user id id
  • Laravel 社交名流:始终获取默认头像

    我允许用户使用 Scialite 注册 仍在启用 openSSL 的 Laravel homestead 上本地工作 它与 FB 配合得很好 除了头像它总是获得默认图像 我正在使用创建应用程序的同一 FB 帐户进行测试 FB 应用程序处于开
  • 在 Postman 中请求受 Azure AD B2C 保护的 Azure 函数应用程序的访问令牌

    我有一个由 Azure Active Directory B2C 租户保护的 AspNetCore 2 0 MVC Web API 我已经能够通过以下 SO 发布使用 Postman 来测试 API 端点 在 Postman 中请求 Azu
  • 如何从 Java 访问 Windows 设备管理器中的信息?

    我有一个串行 USB 设备 并且其中多个设备可以连接到计算机 我需要查询和检索设备连接到的 COM 端口列表 在 Windows 设备管理器中 您可以获得当前连接的设备的 COM 端口 友好名称 该列表是动态的 从注册表中读取不工作 htt
  • MVVM 焦点到文本框

    我如何将焦点集中在TextBox没有指定名称TextBox 目前我正在做以下事情
  • 如何使用 didMoveToView 作为 initWithSize ?

    我将 Xcode 更新到版本 6 从那时起 我就无法使用以前在 Xcode 5 中使用 Objective C 编写的代码了 有一些新文件 GameScene h 和 GameScene m 以及 GameScene sks 而不是 MyS
  • 警告:引用名称“xxx”不明确

    我想知道为什么我收到 refname is ambigeous 的警告 这是否意味着名称以该字符串开头的分支不超过两个 但这里没有 Thanks git checkout B03799 warning refname B03799 is a
  • 在android Gridview中合并行和列

    我正在android中做一个图像查看页面 我需要在某些地方合并行 在某些地方合并列 我们可以在gridview中做到这一点吗 如果我们选择任何合并图像 则应选择整个图像视图 请任何人告诉我一个建议 提前致谢 Try 非对称网格视图 http
  • JAXB 继承冲突 - 重新注释子类

    目前我的项目中有这样的环境 public abstract class Foo private List