JAXB删除XmlRootElement包装器

时间:2013-08-24 10:19:11

标签: xml json jaxb marshalling jaxb2

我有这个@XmlRootElement类Person。

    @XmlRootElement
    class Person {
        private String desc;
    }

,返回内容为

    {"Person": {"desc": "abc"} }

我真的不想要root包装器,所以我希望内容看起来像

    {"desc": "abc"}

我可以通过JaxB完成此操作吗?如果是这样,怎么样?谢谢!

2 个答案:

答案 0 :(得分:4)

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

作为answered by esseplymale JAXB(JSR-222)涵盖XML而不是JSON绑定。 Howvever JAXB经常被直接使用(与Jettison一起使用的JAXB impl将JSON转换为/从StAX事件转换,请参阅:http://blog.bdoughan.com/2011/04/jaxb-and-json-via-jettison.html)和间接(解释JAXB注释子集的JSON绑定实现) 。

以下是利用EclipseLink MOXy作为JAXB提供程序来完成用例的方法。

Java模型

<强>人

以下是您问题中的Person课程。我添加了@XmlAccessorType(XmlAccessType.FIELD)注释,以便我可以避免添加访问器方法(请参阅:http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html)。

import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
class Person {

    private String desc;

}

<强> jaxb.properties

您使用MOXy作为JAXB提供程序,您需要在与域模型相同的程序包中包含名为jaxb.properties的文件,并带有以下条目(请参阅:http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html)。

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

演示代码

<强>演示

演示代码中有几点需要注意:

  1. JAXBContextProperties.MEDIA_TYPE属性用于将MOXy置于JSON绑定模式。
  2. JAXBContextProperties.JSON_INCLUDE_ROOT属性用于告诉MOXy省略根元素。
  3. 当省略根元素时,您需要使用unmarshal参数之一的Class方法告诉M​​OXy您要解组的类型。
  4. import java.util.*;
    import javax.xml.bind.*;
    import javax.xml.transform.stream.StreamSource;
    import org.eclipse.persistence.jaxb.JAXBContextProperties;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            Map<String, Object> properties = new HashMap<String, Object>(2);
            properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
            properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false);
            JAXBContext jc = JAXBContext.newInstance(new Class[] {Person.class}, properties);
    
            Unmarshaller unmarshaller = jc.createUnmarshaller();
            StreamSource json = new StreamSource("src/forum18417466/input.json");
            Person person = unmarshaller.unmarshal(json, Person.class).getValue();
    
            Marshaller marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.marshal(person, System.out);
        }
    
    }
    

    <强> input.json /输出

    {
       "desc" : "abc"
    }
    

答案 1 :(得分:3)

JAXB是XML的API,而不是JSON。

但是,有一些JSON库(至少是Jackson)可以使用JAXB注释。我不知道你正在使用哪一个,所以我不知道如何最好地帮助。 (如果你在Jersey框架中使用它,它使用Jackson进行JSON序列化。)你需要配置你正在使用的任何JSON库,以便能够配置&#34;包装&#34; JSON输出中的根元素。

我写了这个快速的Groovy脚本来测试杰克逊:

@Grab('com.fasterxml.jackson.core:jackson-databind:2.2.2')
import javax.xml.bind.annotation.XmlRootElement
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature

@XmlRootElement
public class Person {
  public String desc = "howdy"
}

Person p = new Person()
ObjectMapper om = new ObjectMapper().enable(SerializationFeature.WRAP_ROOT_VALUE)
println om.writeValueAsString(p)

如上所述,它输出JSON:

{"Person":{"desc":"howdy"}}

如果你拿出.enable(SerializationFeature.WRAP_ROOT_VALUE)部分,它会给你:

{"desc":"howdy"}

因此,如果您使用的是Jackson,那么在幕后使用的ObjectMapper似乎设置为WRAP_ROOT_VALUE,您只需将其关闭即可。