문제

매우 간단한 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

JaxB가 문자열, 정수 등과 같은 간단한 유형에 대한 기본 설정이 있기를 바랐습니다. 내가 상상했던 것은 다음과 같습니다.


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

이 방법을 작동시키는 가장 쉬운 방법은 무엇입니까?

도움이 되었습니까?

해결책

@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;
    }
}

제네릭을 사용하므로 문자열 이외의 다른 클래스에서 사용할 수 있습니다. 이제 응용 프로그램 코드는 간단합니다.


    @GET
    @Path("/test2")
    public JaxbList test2(){
        List list=new Vector();
        list.add("a");
        list.add("b");
        return new JaxbList(list);
    }

이 간단한 클래스가 JAXB 패키지에 존재하지 않는 이유는 무엇입니까? 누구든지 다른 곳에서 그런 것을 본 사람이 있습니까?

다른 팁

@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();
}

여러 클래스의 요소가 포함 된 목록에 대한 목록 래퍼를 작성하려는 경우 X 래퍼 클래스를 작성하지 않고 클래스 유형에 따라 개별 XMLELEMENT 이름을 제공하려는 경우 @XmlMixed 주석. 그렇게함으로써 jaxb는 @XmlRootElement. 그렇게 할 때는 어떤 클래스가 목록에있을 수 있는지 지정해야합니다. @XmlSeeAlso

예시:

목록에서 가능한 클래스

@XmlRootElement(name="user")
public class User {/*...*/}

@XmlRootElement(name="entry")
public class LogEntry {/*...*/}

래퍼 클래스

@XmlRootElement(name="records")
@XmlSeeAlso({User.class, LogEntry.class})
public static class JaxbList<T>{

    protected List<T> records;

    public JaxbList(){}

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

    @XmlMixed 
    public List<T> getRecords(){
        return records;
    }
}

예시:

List l = new List();
l.add(new User("userA"));
l.add(new LogEntry(new UserB()));


XStream xStream = new XStream();
String result = xStream.toXML(l);

결과:

<records>
    <user>...</user>
    <entry>...</entry>
</records>

대체로 @XmlElementRef 주석

@XmlRootElement(name="records")
@XmlSeeAlso({User.class, LogEntry.class})
public static class JaxbList<T>{

    protected List<T> records;

    public JaxbList(){}

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

    @XmlElementRefs({
        @XmlElementRef(name="item", type=Object.class),
        @XmlElementRef(name="user", type=User.class),
        @XmlElementRef(name="entry", type=LogEntry.class)
    })
    public List<T> getRecords(){
        return records;
    }
}

개인 블로그에서 게시하다, 특정 것을 만들 필요는 없습니다 JaxbList < T > 물체.

문자열 목록이있는 개체를 가정합니다.

@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;
    }

}

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(" ");

}

다음을 생성합니다.

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

이것은 할 수 있습니다 많이 훌륭합니다 xstream 도서관. 포장지도없고 주석이 없습니다.

대상 XML

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

직렬화

(String 소문자를 사용하여 별명을 피할 수 있습니다 string 태그이지만 OP의 코드를 사용했습니다)

List <String> list = new ArrayList <String>();
list.add("a");
list.add("b");

XStream xStream = new XStream();
xStream.alias("Strings", List.class);
xStream.alias("String", String.class);
String result = xStream.toXML(list);

사제화

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 = new XStream();
xStream.alias("Strings", String[].class);
xStream.alias("String", String.class);
String[] result = (String[])xStream.fromXML(file);

XStream 인스턴스는 스레드 안전이며 미리 구성되어 코드 금액이 1 라이너로 축소 될 수 있습니다.

XStream은 JAX-RS 서비스를위한 기본 직렬화 메커니즘으로도 사용할 수 있습니다. 저지에서 Xstream을 막는 예를 찾을 수 있습니다 여기

나는이 패턴을 몇 번 만났다. 가장 쉬운 방법은 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);}
 }

Javax.rs (Jax-Rs)와 함께 작업하면 래퍼 세트를 엔티티로 설정 한 응답 객체를 반환합니다.

마침내 나는 그것을 사용하여 해결했다 JacksonJaxbJsonProvider 봄에는 약간의 변화가 필요합니다 context.xml 그리고 Maven pom.xml

당신의 봄에 context.xml 추가하다 JacksonJaxbJsonProvider ~로 <jaxrs:server>:

<jaxrs:server id="restService" address="/resource">
    <jaxrs:providers>
        <bean class="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider"/>
    </jaxrs:providers>
</jaxrs:server>

Maven pom.xml에서 추가 :

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-jaxrs</artifactId>
    <version>1.9.0</version>
</dependency>

user1의 예는 저에게 잘 작동했습니다. 그러나 경고로 @xmlseealso 주석을 추가하지 않는 한 간단한 문자열/정수 유형 이외의 다른 방법으로 작동하지 않습니다.

@XmlRootElement(name = "List")
@XmlSeeAlso(MovieTicket.class)
public class MovieTicketList {
    protected List<MovieTicket> list;

이것은 전체 애플리케이션에서 단일 일반 목록 클래스를 사용하지 못하지만 괜찮습니다. 또한이 명백한 클래스가 JAXB 패키지에 존재하지 않는 이유를 설명 할 수도 있습니다.

jaxblist 내부의 특정 클래스와 함께 @xmlseealso 태그를 추가하십시오. httpmessagenotwaridexception을 던지는 것이 매우 중요합니다

내가 찾으면 시간을 절약했을 것입니다 RESASY JACKSON 제공 업체 더 빨리.

그냥 추가하십시오 RESASY JACKSON 제공 업체 JAR. 엔티티 포장지가 없습니다. XML 주석이 없습니다. 맞춤 메시지 신체 작가가 없습니다.

Jersey Project에서 Maven을 사용하는 경우 POM.XML에서 아래에 추가하고 JAXB가 모델 클래스를 감지하고 미디어 유형 응용 프로그램 XML로 목록을 변환 할 수 있도록 프로젝트 종속성을 업데이트하십시오.

<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>2.2.11</version>
</dependency>

보다 일반적인 솔루션을 위해서는 최상위 레벨 목록의 JAXB-XML 직렬화를 위해서는 1 개의 새로운 클래스 만 작성해야합니다.이 질문에 제공된 솔루션을 확인하십시오.

JAXB를 프로그래밍 방식으로 구성 할 수 있습니까?

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();

}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top