使用JAXB对对象数组进行JSON编组

时间:2013-11-18 14:37:05

标签: json jaxb moxy xmlanyelement

使用MOXy我试图将这样的java类编组为JSON:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Request {
   String method;
   @XmlAnyElement(lax=true)
   Object[] arguments;
}

我希望有类似的东西:

{
    "method": "test",
    "arguments": ["a", "b"]
}

但JSON输出结果为:

{
    "method": "test",
    "value": ["a", "b"]
}

value来自哪里?

如果我在参数字段上放置@XmlElementWrapper,那就更糟了:

{
    "method":"test",
    "arguments":"a""value":["b"]
}

我的JUnit TestCase看起来像这样:

import static org.junit.Assert.assertEquals;

import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import javax.xml.bind.*;
import javax.xml.bind.annotation.*;

import org.junit.Test;

public class JsonRequestTest {

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public static class Request {
    String method;

    @XmlAnyElement(lax=true)
    Object[] arguments;
} // InvocationRequest

@Test
public void testObjectArray() throws JAXBException {
    System.setProperty(JAXBContext.class.getName(), "org.eclipse.persistence.jaxb.JAXBContextFactory");
    Map<String, Object> props= new HashMap<String, Object>();
    props.put("eclipselink.media-type", "application/json");
    props.put("eclipselink.json.include-root", false);

    JAXBContext ctx = JAXBContext.newInstance(new Class<?>[]{Request.class},props);
    Marshaller m = ctx.createMarshaller();
    StringWriter writer = new StringWriter();
    Request req = new Request(); 
    req.method="test";
    req.arguments = new Object[]{"a","b"};
    m.marshal(req, writer);
    assertEquals("{\"method\":\"test\", \"arguments\":[\"a\",\"b\"]}", writer.toString());
}
} // class JsonRequestTest

1 个答案:

答案 0 :(得分:1)

注意:我是EclipseLink MOXy主管,是JAXB (JSR-222)专家组的成员。

TL:DR

您可以设置以下属性来覆盖value键。

    props.put(MarshallerProperties.JSON_VALUE_WRAPPER, "arguments");

完整测试用例

以下是完整的工作测试案例。除了设置属性之外,我还删除了控制文档中的额外空间以使测试通过。

import static org.junit.Assert.assertEquals;

import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import javax.xml.bind.*;
import javax.xml.bind.annotation.*;

import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.junit.Test;

public class JsonRequestTest {

    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    public static class Request {
        String method;

        @XmlAnyElement(lax = true)
        Object[] arguments;
    } // InvocationRequest

    @Test
    public void testObjectArray() throws JAXBException {
        System.setProperty(JAXBContext.class.getName(),
                "org.eclipse.persistence.jaxb.JAXBContextFactory");
        Map<String, Object> props = new HashMap<String, Object>();
        props.put("eclipselink.media-type", "application/json");
        props.put("eclipselink.json.include-root", false);
        props.put(MarshallerProperties.JSON_VALUE_WRAPPER, "arguments");

        JAXBContext ctx = JAXBContext.newInstance(
                new Class<?>[] { Request.class }, props);
        Marshaller m = ctx.createMarshaller();
        StringWriter writer = new StringWriter();
        Request req = new Request();
        req.method = "test";
        req.arguments = new Object[] { "a", "b" };
        m.marshal(req, writer);
        assertEquals("{\"method\":\"test\",\"arguments\":[\"a\",\"b\"]}",
                writer.toString());
    }

} // class JsonRequestTest

@XmlElementWrapper问题

我已针对@XmlElementWrapper的问题打开了以下错误: