繁体   English   中英

在Jersey 2.2 JAX-RS下将名称空间与JAXB和JSON一起使用

[英]Using namespaces with JAXB and JSON under Jersey 2.2 JAX-RS

我正在使用xjc编译具有名称空间和ANY元素的XML模式。 我将根据需要包括来自外部命名空间的元素,并且需要处理其中包含新版本的元素定义,或者可能是来自另一个名称空间的同名元素的情况。 显然,它的XML版本运行良好,并且我为客户端的所有元素都获得了正确的QNAME,但是对于JSON,我得到了仅包含元素名称的不合格QNAME。 这意味着我无法区分一个命名空间中的和元素,而第二个命名空间中的和另一个元素“ bob”。

我已经阅读了所有可以找到的资料,并且相信这是我需要在服务器端执行的操作,但是,我不知道在客户端需要什么:

@Provider
final static class JsonMoxyConfigurationContextResolver implements ContextResolver<MoxyJsonConfig> {

    @Override
    public MoxyJsonConfig getContext(Class<?> objectType) {
        final MoxyJsonConfig configuration = new MoxyJsonConfig();

        Map<String, String> namespacePrefixMapper = new HashMap<String, String>(2);
        namespacePrefixMapper.put("http://schema.jaxbmoxy.examples.jersey.glassfish.org/2013/08/customer", "c");
        namespacePrefixMapper.put("http://schema.jaxbmoxy.examples.jersey.glassfish.org/2013/08/other", "o");

        configuration.setNamespacePrefixMapper(namespacePrefixMapper);
        configuration.setNamespaceSeparator('.');

        return configuration;
    }
}

“ c”模式是我定义的基本模式,“ o”模式保存了将通过ANY合并的元素定义。 对于下面的示例,我将从外部名称空间导入o.stats和o.email。 以下是在服务器端生成的JSON:

{"c.customer": [
    {
        "id": "3",
        "personal-info": {
            "name": "Bobby Boogie",
            "o.stats": [{
                "age": "45",
                "height": "160 cm",
                "weight": "70 kg"
            }]
        },
        "contact-info": {
            "address": {
                "city": "My Town",
                "street": "123 Any Street",
                "country": "CA"
            },
            "phone-number": [
                {
                    "type": "work",
                    "value": "613-555-1111"
                },
                {
                    "type": "cell",
                    "value": "613-555-2222"
                }
            ]
        }
    },
    {
        "id": "2",
        "personal-info": {
            "name": "Fred Finkleman",
            "o.stats": [{
                "age": "55",
                "height": "182 cm",
                "weight": "86 kg"
            }]
        },
        "contact-info": {
            "address": {
                "city": "Fredsville",
                "street": "1 Happy Street",
                "country": "US"
            },
            "phone-number": [
                {
                    "type": "work",
                    "value": "613-555-1111"
                },
                {
                    "type": "cell",
                    "value": "613-555-2222"
                }
            ],
            "o.email": ["fred@email.com"]
        }
    },
    {
        "id": "1",
        "personal-info": {
            "name": "Tom Dooley",
            "o.stats": [{
                "age": "45",
                "height": "160 cm",
                "weight": "70 kg"
            }]
        },
        "contact-info": {
            "address": {
                "city": "My Town",
                "street": "123 Any Street",
                "country": "CA"
            },
            "phone-number": [
                {
                    "type": "work",
                    "value": "613-555-1111"
                },
                {
                    "type": "cell",
                    "value": "613-555-2222"
                }
            ]
        }
    }
]}

我需要在客户端使用什么配置代码,以便我可以使其正常运行? 目前,我有以下内容:

@Override
protected void configureClient(ClientConfig clientConfig) {
    clientConfig.register(new MoxyXmlFeature());
    new ResourceConfig().property(MarshallerProperties.JSON_NAMESPACE_SEPARATOR, ".");
}

谢谢!

您还需要设置MarshallerProperties.NAMESPACE_PREFIX_MAPPER属性,以匹配您在服务器端设置的属性。

编辑:我觉得上面提供的Blaise答案是正确的,但是,它引入了另一个问题,我只能认为是Jersey 2.2下的错误。 这是我根据Blaise的答案创建的客户代码段:

@Override
protected void configureClient(ClientConfig clientConfig) {
    Map<String, String> namespacePrefixMapper = new HashMap<String, String>(2);
    namespacePrefixMapper.put("http://schema.jaxbmoxy.examples.jersey.glassfish.org/2013/08/customer", "c");
    namespacePrefixMapper.put("http://schema.jaxbmoxy.examples.jersey.glassfish.org/2013/08/other", "o");

    clientConfig.register(new MoxyXmlFeature());
    clientConfig.register(new MoxyJsonFeature());
    clientConfig.property(MarshallerProperties.NAMESPACE_PREFIX_MAPPER, namespacePrefixMapper);
    clientConfig.property(MarshallerProperties.JSON_NAMESPACE_SEPARATOR, '.');
}

在客户端,我现在在处理传入的JSON时得到一个NPE:

javax.ws.rs.ProcessingException: Unexpected error during response processing.
at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:767)
at org.glassfish.jersey.client.JerseyInvocation.access$500(JerseyInvocation.java:90)
at org.glassfish.jersey.client.JerseyInvocation$2.call(JerseyInvocation.java:671)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:422)
at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:667)
at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:396)
at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:296)
at org.glassfish.jersey.examples.jaxbmoxy.MoxyAppTest.testJsonCustomer(MoxyAppTest.java:172)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:53)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:123)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:104)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:164)
at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:110)
at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:175)
at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcessWhenForked(SurefireStarter.java:107)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:68)
Caused by: java.lang.NullPointerException
at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:264)
at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:443)
at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:424)
at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:241)
at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:443)
at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:296)
at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:443)
at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:424)
at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:241)
at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parseRoot(JSONReader.java:174)
at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:125)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:972)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:425)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:375)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:705)
at org.eclipse.persistence.oxm.XMLUnmarshaller.unmarshal(XMLUnmarshaller.java:655)
at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:301)
at org.eclipse.persistence.jaxb.rs.MOXyJsonProvider.readFrom(MOXyJsonProvider.java:580)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:188)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:134)
at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:988)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:833)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:768)
at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:96)
at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:761)
... 41 more

现在一切都不会丢失。 我可以通过添加属性前缀处理来解决此问题。 在服务器端,我添加到JsonMoxyConfigurationContextResolver.getContext()

configuration.setAttributePrefix("@"); 

在客户端,我将以下内容添加到configureClient()

clientConfig.property(MarshallerProperties.JSON_ATTRIBUTE_PREFIX, "@");

现在,我可以正确处理传入的JSON,并将名称空间添加到所包含的JAXB元素的QNAME中。

感谢您的帮助!!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM