当指定UTF-8编码时,MOXy JAXB编组Unicode(u + 2019)的无效控制字符

THX*_*138 6 json jaxb utf-8 marshalling moxy

当我尝试使用Eclipse Moxy将类编组为JSON时,我遇到了一个非常恼人的错误.

我的一个域类中有一个具有以下值的属性:"the City’s original city site"其中包含代码点u + 2019(')

当Jaxb试图编组这个值时,我莫名其妙地找回了一个奇怪的控件: "Citys original city site"

这会导致无效的JSON在解码时返回空值.我和杰克逊一起尝试了这个,并且收到了一个ascii转义字符,这仍然是错误的,但它至少会产生有效的JSON!

Moxy应该能够正确输出,因为'是一个有效的unicode字符,并且在JSON中是有效的.我能做些什么来正确输出'(和任何其他unicode字符),最好将这个不必要的字符转换为常规撇号.

这是我的提供者类:

@Provider
@Component("customMOXyJsonProvider")    
public class CustomMOXyJsonProvider extends MOXyJsonProvider {

    @Override
    protected void preWriteTo(Object object, Class<?> type, Type genericType,
                              Annotation[] annotations, MediaType mediaType,
                              MultivaluedMap<String, Object> httpHeaders, Marshaller marshaller)
            throws JAXBException {
        marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, true);
        marshaller.setProperty(Marshaller.JAXB_ENCODING,"UTF-8");
    }

}
Run Code Online (Sandbox Code Playgroud)

我正在使用Moxy的2.5.1版本.

    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>org.eclipse.persistence.moxy</artifactId>
        <version>2.5.1</version>
    </dependency>
Run Code Online (Sandbox Code Playgroud)

我的系统中有几个组件理论上可能搞砸了这些值(postgres,jdbc,hibernate,cxf和tomcat),但我已经通过测试确定该值正确存储在我的域类中 - 然后损坏,就像Elliot Spitzer一样在编组阶段,拜访一名妓女.

bdo*_*han 4

注意: 我是EclipseLink JAXB (MOXy) 的负责人,也是JAXB (JSR-222)专家组的成员。

\n\n

更新#3

\n\n

该问题现已在 EclipseLink 2.5.2 和 2.6.0 流中得到修复。从 2013 年 10 月 10 日开始,您将可以从以下位置下载每晚版本:

\n\n\n\n

或者从 Maven 中使用

\n\n
<dependency>\n    <groupId>org.eclipse.persistence</groupId>\n    <artifactId>org.eclipse.persistence.moxy</artifactId>\n    <version>2.5.2-SNAPSHOT</version>\n</dependency>\n
Run Code Online (Sandbox Code Playgroud)\n\n

\n\n
<repository>\n    <id>oss.sonatype.org</id>\n    <name>OSS Sonatype Staging</name>\n    <url>https://oss.sonatype.org/content/groups/staging</url>\n</repository>\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

更新#2

\n\n

以下错误可用于跟踪我们在此问题上的进展:

\n\n\n\n
\n\n

更新#1

\n\n

您的用例在 EclipseLink 2.5.0 中工作。我们在 EclipseLink 2.5.1 中进行的性能修复导致了此故障:

\n\n\n\n
\n\n

原答案

\n\n

我们的编组中似乎存在一个错误,而JSONOutputStream的编组中不存在该错误Writer(XML 工作正常)。以下是我的快速调查发现的内容。一旦我有更多信息,我会更新我的答案。

\n\n

Java模型

\n\n
public class Foo {\n\n    private String bar;\n\n    public String getBar() {\n        return bar;\n    }\n\n    public void setBar(String bar) {\n        this.bar = bar;\n    }\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

演示代码

\n\n
import java.io.OutputStreamWriter;\nimport java.util.*;\nimport javax.xml.bind.*;\nimport javax.xml.bind.Marshaller;\nimport org.eclipse.persistence.jaxb.JAXBContextProperties;\n\npublic class Demo {\n\n    public static void main(String[] args) throws Exception {\n        Map<String, Object> properties = new HashMap<String, Object>();\n        properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");\n        properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false);\n        JAXBContext jc = JAXBContext.newInstance(new Class[] {Foo.class}, properties);\n\n        Foo foo = new Foo();\n        foo.setBar("the City\xe2\x80\x99s original city site");\n\n\n        Marshaller marshaller = jc.createMarshaller();\n        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);\n\n        // Broken\n        marshaller.marshal(foo, System.out);\n\n        // Works\n        marshaller.marshal(foo, new OutputStreamWriter(System.out));\n    }\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出

\n\n
{\n   "bar" : "the Citys original city site"\n}{\n   "bar" : "the City\xe2\x80\x99s original city site"\n}\n
Run Code Online (Sandbox Code Playgroud)\n