java 我如何让 Groovy 和 JAXB 一起玩得很好

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1161147/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 15:26:02  来源:igfitidea点击:

How do I get Groovy and JAXB to play nice together

javagroovyjaxb

提问by Hymanie

I am trying to get JAXB to work with a groovy class of mine, however, it appears it doesn't work but the java version does. Here is the code...

我试图让 JAXB 与我的一个 groovy 类一起工作,但是,它似乎不起作用,但 java 版本可以。这是代码...

Here are the Scenarios:

以下是场景:

If 2 and 3 are uncommented it works fine.

如果 2 和 3 没有被注释,它就可以正常工作。

If 1 and 4 are uncommented I get:

如果 1 和 4 未注释,我会得到:

 com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException:
       2 counts of IllegalAnnotationExceptions
 groovy.lang.MetaClass is an interface, and JAXB can't handle interfaces.

If 1 and 5 are uncommented I get:

如果 1 和 5 未注释,我会得到:

  javax.xml.bind.JAXBException: class org.oclc.presentations.simplejaxb.PlayerGroovy
        nor any of its super class is known to this context.

Any ideas?

有任何想法吗?

Java:

爪哇:

    import javax.xml.bind.annotation.XmlRootElement;

    @XmlRootElement
    public class Player {
    }

Groovy:

常规:

    import javax.xml.bind.annotation.XmlRootElement

    @XmlRootElement
    public class PlayerGroovy {
    }

Test:

测试:

    import org.junit.Test
    import javax.xml.bind.JAXBContext
    import javax.xml.bind.Marshaller
    import org.junit.Assert

    class PlayerTest {
        @Test
        public void testJaXB(){
            //1 PlayerGroovy player = new PlayerGroovy()
            //2 Player player = new Player()
            StringWriter writer = new StringWriter();
            //3 JAXBContext context = JAXBContext.newInstance(Player.class);
            //4 JAXBContext context = JAXBContext.newInstance(PlayerGroovy.class);
            //5 JAXBContext context = JAXBContext.newInstance(PlayerGroovy.getClass());
            Marshaller m = context.createMarshaller();
            m.marshal(player, writer);
            println(writer)
            Assert.assertTrue(true)
        }
    }

回答by Chris Dail

Uncommenting 1 and 4 is the correct way to set JAXB up with Groovy. The reason it is not working is that each Groovy Class has a metaClass property on it. JAXB is trying to expose this as a JAXB property which obviously fails. Since you don't declare the metaClass property yourself, it is not possible to annotate it to have JAXB ignore it. Instead you and set the XmlAccessType to NONE. This disable's JAXB's auto-discovery of properties to expose as XML elements. After you do that, you need to explicitly declare any fields you want exposed.

取消注释 1 和 4 是使用 Groovy 设置 JAXB 的正确方法。它不工作的原因是每个 Groovy Class 都有一个 metaClass 属性。JAXB 试图将其公开为显然失败的 JAXB 属性。由于您没有自己声明 metaClass 属性,因此无法对其进行注释以让 JAXB 忽略它。相反,您将 XmlAccessType 设置为 NONE。这将禁用 JAXB 自动发现属性以公开为 XML 元素。执行此操作后,您需要显式声明要公开的任何字段。

Example:

例子:

@XmlAccessorType( XmlAccessType.NONE )
@XmlRootElement
public class PlayerGroovy {
    @XmlAttribute
    String value
}

回答by Steve Ardis

I was having the same problem while exposing a Grails GORM object. After researching the solution posted above, using @XmlAccessorType( XmlAccessType.NONE ), I quickly grew tired of marking everything as @XmlAttribute.

我在公开 Grails GORM 对象时遇到了同样的问题。在研究了上面发布的解决方案后,使用@XmlAccessorType( XmlAccessType.NONE ),我很快就厌倦了将所有内容标记为@XmlAttribute.

I'm having plenty of success using:

我使用以下方法取得了很多成功:

@XmlAccessorType( XmlAccessType.FIELD )
@XmlRootElement
public class PlayerGroovy {
    String value
}

See: XmlAccessType

请参阅:XmlAccessType

Thanks to the original answer for getting me started in the right direction.

感谢原始答案让我朝着正确的方向开始。

回答by ngreen

The solution does not seem to work on an abstract subclass. I think it's because the compiler does not generate the getMetaClassoverride code. I ended up mimicking the steps from this questionas follows:

该解决方案似乎不适用于抽象子类。我认为这是因为编译器不会生成getMetaClass覆盖代码。我最终模仿了这个问题的步骤如下:

@XmlAccessorType(XmlAccessType.NONE)
package groovy.lang;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;

Yes, it's kinda weird. In my case, I have code like this:

是的,这有点奇怪。就我而言,我有这样的代码:

package pkg;
abstract class ScriptMomma extends groovy.lang.Script {
    // write some nice supporting code here
}

And to execute my scripts, I have:

为了执行我的脚本,我有:

def config = new org.codehaus.groovy.control.CompilerConfiguration()
config.scriptBaseClass = 'pkg.ScriptMomma'
ScriptMomma mine = new GroovyShell(config).evaluate(scriptFile, 'TheOne')

I'd prefer a better solution, but right now this is all I have.

我更喜欢更好的解决方案,但现在这就是我所拥有的。