Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/rest/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用JAXB解组/封送列表<;字符串>;_Java_Rest_Jaxb - Fatal编程技术网

Java 使用JAXB解组/封送列表<;字符串>;

Java 使用JAXB解组/封送列表<;字符串>;,java,rest,jaxb,Java,Rest,Jaxb,我正在尝试创建一个非常简单的REST服务器。我有一个测试方法,它将返回一个字符串列表。代码如下: @GET @Path("/test2") public List test2(){ List list=new Vector(); list.add("a"); list.add("b"); return list; } 它给出了以下错误: SEVERE: A message body writer for Java type, class java.util.V

我正在尝试创建一个非常简单的REST服务器。我有一个测试方法,它将返回一个字符串列表。代码如下:


@GET
@Path("/test2")
public List test2(){
    List list=new Vector();
    list.add("a");
    list.add("b");
    return list;
}
它给出了以下错误:

SEVERE: A message body writer for Java type, class java.util.Vector, and MIME media type, application/octet-stream, was not found 严重:Java类型的消息体编写器, 类java.util.Vector和MIME媒体类型, 找不到应用程序/八位字节流 我希望JAXB对字符串、整数等简单类型有一个默认设置。我想没有。以下是我的想象:


<Strings>
  <String>a</String>
  <String>b</String>
</Strings>

A.
B

让这个方法工作的最简单的方法是什么?

我已经多次遇到这种模式,我发现最简单的方法是用JaxB注释定义一个内部类。(无论如何,您可能需要定义根标记名)

所以你的代码看起来像这样

@GET
@Path("/test2")
public Object test2(){
   MyResourceWrapper wrapper = new MyResourceWrapper();
   wrapper .add("a");
   wrapper .add("b");
   return wrapper ;
}

@XmlRootElement(name="MyResource")
private static class MyResourceWrapper {
       @XmlElement(name="Item")
       List<String> list=new ArrayList<String>();
       MyResourceWrapper (){}

       public void add(String s){ list.add(s);}
 }
@GET
@路径(“/test2”)
公共对象test2(){
MyResourceWrapper=新的MyResourceWrapper();
(a)加入(“a”);
(b)加入(“b”);
返回包装器;
}
@XmlRootElement(name=“MyResource”)
私有静态类MyResourceWrapper{
@xmlement(name=“Item”)
列表=新的ArrayList();
MyResourceWrapper(){}
public void add(字符串s){list.add(s);}
}

如果您使用javax.rs(jax-rs),我将返回响应对象,并将包装器集作为其实体

我使用了@LiorH的示例,并将其扩展为:


@XmlRootElement(name="List")
public class JaxbList<T>{
    protected List<T> list;

    public JaxbList(){}

    public JaxbList(List<T> list){
        this.list=list;
    }

    @XmlElement(name="Item")
    public List<T> getList(){
        return list;
    }
}

为什么JAXB包中不存在这个简单的类?有人在其他地方看到过类似的东西吗?

User1的例子对我很有用。但是,作为一个警告,除了简单的字符串/整数类型之外,它不适用于任何其他类型,除非您添加@xmlseeald注释:

@XmlRootElement(name = "List")
@XmlSeeAlso(MovieTicket.class)
public class MovieTicketList {
    protected List<MovieTicket> list;
@XmlRootElement(name=“List”)
@XMLSEEALLO(MovieTicket.class)
公共级电影目录{
受保护名单;
虽然它阻止我在整个应用程序中使用单一的泛型列表类,但它仍然可以正常工作。这也可以解释为什么JAXB包中不存在这个看似显而易见的类。

@GET
@GET
@Path("/test2")
public Response test2(){
   List<String> list=new Vector<String>();
   list.add("a");
   list.add("b");

   final GenericEntity<List<String>> entity = new GenericEntity<List<String>>(list) { };
   return Response.ok().entity(entity).build();
}
@路径(“/test2”) 公众回应测试2(){ 列表=新向量(); 列表。添加(“a”); 列表。添加(“b”); 最终通用实体=新通用实体(列表){}; 返回Response.ok().entity(entity.build(); }
使用美妙的库,这可以更轻松地完成。无包装,无注释

目标XML 反序列化 反序列化为ArrayList

XStream xStream = new XStream();
xStream.alias("Strings", ArrayList.class);
xStream.alias("String", String.class);
xStream.addImplicitArray(ArrayList.class, "elementData");
List <String> result = (List <String>)xStream.fromXML(file);
注意,XStream实例是线程安全的,可以预先配置,从而将代码量缩减到一行


XStream还可以用作JAX-RS服务的默认序列化机制。在Jersey中插入XStream的示例可以找到

以防任何人想要为包含多个类的元素的列表编写一个列表包装器,并且想要根据类类型给出一个单独的XmlElement名称,而不需要编写X包装器cla您可以使用
@XmlMixed
注释。 通过这样做,JAXB根据
@XmlRootElement
设置的值命名列表中的项。 执行此操作时,您必须使用
@xmlsee也

示例:

列表中可能的类

@XmlRootElement(name=“user”)
公共类用户{/*…*/}
@XmlRootElement(name=“entry”)
公共类日志项{/*…*/}
包装类

@XmlRootElement(name=“records”)
@XMLSEEALLO({User.class,LogEntry.class})
公共静态类JaxbList{
受保护名单记录;
公共JaxbList(){}
公共JaxbList(列表){
这个。记录=列表;
}
@混合
公共列表记录(){
退货记录;
}
}
例如:

List l=新列表();
l、 添加(新用户(“用户A”);
l、 添加(新日志条目(新UserB());
XStream XStream=新的XStream();
字符串结果=xStream.toXML(l);
结果:


...
...
或者,您可以使用
@xmlementref
注释直接在包装类内部指定xmlement名称

@XmlRootElement(name=“records”)
@XMLSEEALLO({User.class,LogEntry.class})
公共静态类JaxbList{
受保护名单记录;
公共JaxbList(){}
公共JaxbList(列表){
这个。记录=列表;
}
@XmlElementRefs({
@xmlementref(name=“item”,type=Object.class),
@xmlementref(name=“user”,type=user.class),
@xmlementref(name=“entry”,type=LogEntry.class)
})
公共列表记录(){
退货记录;
}
}
从个人博客中,无需创建特定的
JaxbList
对象

假设对象具有字符串列表:

@XmlRootElement
public class ObjectWithList {

    private List<String> list;

    @XmlElementWrapper(name="MyList")
    @XmlElement
    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

}
@XmlRootElement
公共类ObjectWithList{
私人名单;
@XmlElementWrapper(name=“MyList”)
@XmlElement
公共列表getList(){
退货清单;
}
公共无效集合列表(列表){
this.list=列表;
}
}
JAXB往返:

public static void simpleExample() throws JAXBException {

    List<String> l = new ArrayList<String>();
    l.add("Somewhere");
    l.add("This and that");
    l.add("Something");

    // Object with list
    ObjectWithList owl = new ObjectWithList();
    owl.setList(l);

    JAXBContext jc = JAXBContext.newInstance(ObjectWithList.class);
    ObjectWithList retr = marshallUnmarshall(owl, jc);

    for (String s : retr.getList()) {
        System.out.println(s);
    } System.out.println(" ");

}
public static void simpleExample()抛出JAXBEException{
列表l=新的ArrayList();
l、 添加(“某处”);
l、 添加(“这个和那个”);
l、 添加(“某物”);
//具有列表的对象
ObjectWithList owl=新建ObjectWithList();
owl.集合列表(l);
JAXBContext jc=JAXBContext.newInstance(ObjectWithList.class);
ObjectWithList retr=MarshallLunmarshall(owl,jc);
for(字符串s:retr.getList()){
系统输出打印项次;
}System.out.println(“”);
}
产生以下结果:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<objectWithList>
    <MyList>
        <list>Somewhere</list>
        <list>This and that</list>
        <list>Something</list>
    </MyList>
</objectWithList>

某处
这个和那个
某物

确保在JaxbList中添加带有特定类的@xmlseea标记。这一点非常重要,否则它会引发HttpMessageNotWritableException

如果我早点找到Resteasy Jackson Provider我会节省时间


只需添加Resteasy Jackson提供程序JAR。无实体包装、无XML注释、无自定义消息正文编写器。

最后,我使用

XStream xStream = new XStream();
xStream.alias("Strings", String[].class);
xStream.alias("String", String.class);
String[] result = (String[])xStream.fromXML(file);
@XmlRootElement
public class ObjectWithList {

    private List<String> list;

    @XmlElementWrapper(name="MyList")
    @XmlElement
    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

}
public static void simpleExample() throws JAXBException {

    List<String> l = new ArrayList<String>();
    l.add("Somewhere");
    l.add("This and that");
    l.add("Something");

    // Object with list
    ObjectWithList owl = new ObjectWithList();
    owl.setList(l);

    JAXBContext jc = JAXBContext.newInstance(ObjectWithList.class);
    ObjectWithList retr = marshallUnmarshall(owl, jc);

    for (String s : retr.getList()) {
        System.out.println(s);
    } System.out.println(" ");

}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<objectWithList>
    <MyList>
        <list>Somewhere</list>
        <list>This and that</list>
        <list>Something</list>
    </MyList>
</objectWithList>
<jaxrs:server id="restService" address="/resource">
    <jaxrs:providers>
        <bean class="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider"/>
    </jaxrs:providers>
</jaxrs:server>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-jaxrs</artifactId>
    <version>1.9.0</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>2.2.11</version>
</dependency>
public class Wrapper<T> {

private List<T> items = new ArrayList<T>();

@XmlAnyElement(lax=true)
public List<T> getItems() {
    return items;
}

}

//JAXBContext is thread safe and so create it in constructor or 
//setter or wherever:
... 
JAXBContext jc = JAXBContext.newInstance(Wrapper.class, clazz);
... 

public String marshal(List<T> things, Class clazz) {

  //configure JAXB and marshaller     
  Marshaller m = jc.createMarshaller();
  m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

  //Create wrapper based on generic list of objects
  Wrapper<T> wrapper = new Wrapper<T>(things);
  JAXBElement<Wrapper> wrapperJAXBElement = new JAXBElement<Wrapper>(new QName(clazz.getSimpleName().toLowerCase()+"s"), Wrapper.class, wrapper);

  StringWriter result = new StringWriter();
  //marshal!
  m.marshal(wrapperJAXBElement, result);

  return result.toString();

}