jjzjj

java - JAXB 将子类的实例解码到列表中

coder 2024-07-02 原文

假设我想用 xml 表示算术表达式,所以我有:

@XmlRootElement
@XmlTransient
@XmlSeeAlso({Num.class, Add.class})
public abstract class Evaluable
{
    public abstract int eval();
}

@XmlRootElement
@XmlType(name = "num")
public class Num extends Evaluable
{
    @XmlValue
    private int val;

    @Override
    public int eval()
    {
        return val;
    }
}

@XmlRootElement
@XmlType
public class Add extends Evaluable
{
    @XmlAnyElement
    private ArrayList<Evaluable> elems;

    @Override
    public int eval()
    {
        int sum = 0;
        for (Evaluable elem : elems)
        {
            sum += elem.eval();
        }
        return sum;
    }
}

和我的测试用例:

public class RecursiveUnmarshalTest
{
    @Test
    public void testAdd() throws Exception
    {
        String xml = "<add><num>10</num><num>20</num></add>";
        assertEquals(30,
                ((Evaluable) JAXBContext.newInstance(Evaluable.class).createUnmarshaller().unmarshal(new StringReader(
                        xml))).eval());

    }
}

这里的问题是非Evaluable存储在AddArrayList中,原因是类型删除,JAXB没有'不知道元素应该反射(reflect)到哪种类型,所以在 Add 的 eval 中会出现转换错误。

我通过以下方式测试了这一点:

public class Add extends Evaluable
{
    @XmlElements({
            @XmlElement(name = "num", type = Num.class),
            @XmlElement(name = "add", type = Add.class)
    })
    private ArrayList<Evaluable> elems;
...

这将被修复。

但我不想把这张 table 散布到全世界。如果我想附加一些子类型,事情就会变得一团糟。

所以我的问题是哪种注解适合我的情况?或任何类型的解码器系统?

我正在使用 glassfish 的 JAXB,我无法选择要使用的实现。

最佳答案

您可以使用 @XmlElementRef 来获得您正在寻找的行为:

@XmlElementRef
private ArrayList<Evaluable> elems;

更新

it says Evaluable or any of its subclasses are not known to this context

啊,没错,因为您已将 Evaluable 标记为 @XmlTransient,JAXB 忽略它并且不认为它存在。您可能添加了它,因为当您没有它时,您会遇到以下异常。

Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Invalid @XmlElementRef : Type "class forum27826242.Evaluable" or any of its subclasses are not known to this context.
    this problem is related to the following location:
        at private java.util.ArrayList forum27826242.Add.elems
        at forum27826242.Add
        at @javax.xml.bind.annotation.XmlSeeAlso(value=[class forum27826242.Num, class forum27826242.Add])
        at forum27826242.Num

关于java - JAXB 将子类的实例解码到列表中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27826242/

有关java - JAXB 将子类的实例解码到列表中的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  3. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  4. ruby - RVM 使用列表[0] - 2

    是否有类似“RVMuse1”或“RVMuselist[0]”之类的内容而不是键入整个版本号。在任何时候,我们都会看到一个可能包含5个或更多ruby的列表,我们可以轻松地键入一个数字而不是X.X.X。这也有助于rvmgemset。 最佳答案 这在RVM2.0中是可能的=>https://docs.google.com/document/d/1xW9GeEpLOWPcddDg_hOPvK4oeLxJmU3Q5FiCNT7nTAc/edit?usp=sharing-知道链接的任何人都可以发表评论

  5. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  6. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

  7. Ruby——嵌套类和子类是一回事吗? - 2

    下面例子中的Nested和Child有什么区别?是否只是同一事物的不同语法?classParentclassNested...endendclassChild 最佳答案 不,它们是不同的。嵌套:Computer之外的“Processor”类只能作为Computer::Processor访问。嵌套为内部类(namespace)提供上下文。对于ruby​​解释器Computer和Computer::Processor只是两个独立的类。classComputerclassProcessor#Tocreateanobjectforthisc

  8. ruby-on-rails - RSpec:避免使用允许接收的任何实例 - 2

    我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_

  9. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  10. ruby-on-rails - 使用 ruby​​ 将多个实例变量转换为散列的更好方法? - 2

    我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。

随机推荐