2009-07-17 7 views
8

Ich arbeite an einem Projekt, das Jersey verwendet, um Objekte in JSON zu konvertieren. Ich möchte in der Lage sein, verschachtelte Listen zu schreiben, etwa so:Wie marschiere ich verschachtelte Listen als JSON mit Jersey? Ich bekomme ein Array von Nullen oder ein Array von Ein-Element-Wörterbüchern, die ein Array enthalten

{"data":[["one", "two", "three"], ["a", "b", "c"]]} 

Das Objekt, das ich erste Daten als < LinkedList vertreten konvertieren möchte < LinkedList <String> > >, und ich dachte, Jersey würde nur das Richtige tun. Die oben ausgegeben wurde als eine Liste von Nullen:

{"data":[null, null]} 

Nach der Lektüre, dass verschachtelte Objekte müssen gewickelt werden, habe ich versucht, die folgenden:

@XmlRootElement(name = "foo") 
@XmlType(propOrder = {"data"}) 
public class Foo 
{ 
    private Collection<FooData> data = new LinkedList<FooData>(); 

    @XmlElement(name = "data") 
    public Collection<FooData> getData() 
    { 
     return data; 
    } 

    public void addData(Collection data) 
    { 
     FooData d = new FooData(); 
     for(Object o: data) 
     { 
      d.getData().add(o == null ? (String)o : o.toString()); 
     } 
     this.data.add(d); 
    } 

    @XmlRootElement(name = "FooData") 
    public static class FooData 
    { 
     private Collection<String> data = new LinkedList<String>(); 

     @XmlElement 
     public Collection<String> getData() 
     { 
      return data; 
     } 
    } 
} 

Dieser Code gibt, was unten ist, das ist näher an, was Ich möchte:

Ich möchte, dass die ersten Daten eine Liste von Listen sind, nicht eine Liste von Ein-Element-Wörterbüchern. Wie erreiche ich das?

Hier ist meine JAXBContentResolver:

@Provider 
public class JAXBContextResolver implements ContextResolver<JAXBContext> 
{ 
    private JAXBContext context; 
    private Set<Class<?>> types; 

    // Only parent classes are required here. Nested classes are implicit. 
    protected Class<?>[] classTypes = new Class[] {Foo.class}; 

    protected Set<String> jsonArray = new HashSet<String>(1) { 
     { 
      add("data"); 
     } 
    }; 

    public JAXBContextResolver() throws Exception 
    {   
     Map<String, Object> props = new HashMap<String, Object>(); 
     props.put(JSONJAXBContext.JSON_NOTATION, JSONJAXBContext.JSONNotation.MAPPED); 
     props.put(JSONJAXBContext.JSON_ROOT_UNWRAPPING, Boolean.TRUE); 
     props.put(JSONJAXBContext.JSON_ARRAYS, jsonArray); 
     this.types = new HashSet<Class<?>>(Arrays.asList(classTypes)); 
     this.context = new JSONJAXBContext(classTyes, props); 
    } 

    public JAXBContext getContext(Class<?> objectType) 
    { 
     return (types.contains(objectType)) ? context : null; 
    } 
} 

Antwort

5

Haben Sie Jersey-json versucht ??

hinzufügen Jersey-json zu Classpath (oder Ihre Maven Abhängigkeiten)

Dann verwenden:

@Provider 
public class JAXBContextResolver implements ContextResolver<JAXBContext> { 

    private final JAXBContext context; 

    public JAXBContextResolver() throws Exception { 
     this.context = new JSONJAXBContext(JSONConfiguration.natural().build(), "package.of.your.model"); 
    } 

    public JAXBContext getContext(Class<?> objectType) { 
     return context; 
    } 

} 

Sie nur so etwas wie dieses brauchen in Ihrer Ressourcen (unter der Annahme DetailProduit ist Ihr Objekt möchten Sie serialisiert und dass DetailProduit.java ist jaxb markiert und in package.of.your.model)

@GET 
@Produces(MediaType.APPLICATION_JSON) 
@Path("/{code}") 
public DetailProduit getDetailProduit(@PathParam("code") String code) { 
     .... Your Code ........ 
    } 
+0

Ok, ich dachte nur, dass dein Fall komplexer war als ich ... – Arnaudweb

0

Ich weiß, dass die qustion ziemlich alt ist, aber ich auf ein ähnliches Problem gestolpert, aber ich wollte eine Liste der Arrays ie.'List' aufgrund eines Ergebnisses aus einem DB machen, die ich von jpa und eine nativ-Abfrage ohne Verwendung von Entitäten.

Dies ist, wie ich es gelöst:

eine ListWrapper

zuerst erstellt.java:

import java.util.ArrayList; 
import java.util.List; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class ListWrapper extends ArrayList { 

    @SuppressWarnings("unchecked") 
    public ListWrapper() { 
     super(); 
    } 

    public ListWrapper(List list) { 
     super(list); 
    } 
} 

Und dann habe ich eine Klasse AbstractMessageReaderWriterProvider

import org.codehaus.jettison.json.JSONArray; 
import org.codehaus.jettison.json.JSONException; 

import com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider; 

@Provider 
@Produces("*/*") 
@Consumes("*/*") 
public class ListObjectArrayMessagereaderWriterProvider extends AbstractMessageReaderWriterProvider<ListWrapper> { 

    public boolean supports(Class type) { 
     return type == ListWrapper.class; 
    } 

    @Override 
    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { 
     return type == ListWrapper.class; 
    } 

    @Override 
    public ListWrapper readFrom(Class<ListWrapper> type, Type genericType, Annotation[] annotations, MediaType mediaType, 
     MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException { 
     throw new IllegalArgumentException("Not implemented yet."); 
    } 

    @Override 
    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { 
     return type == ListWrapper.class; 
    } 

    @SuppressWarnings("unchecked") 
    @Override 
    public void writeTo(ListWrapper t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, 
     MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException { 

     final Iterator<Object[]> iterator = t.iterator(); 

     OutputStreamWriter writer = new OutputStreamWriter(entityStream, getCharset(mediaType)); 
     final JSONArray jsonArrayOuter = new JSONArray(); 
     while (iterator.hasNext()) { 
      final Object[] objs = iterator.next(); 
      JSONArray jsonArrayInner = new JSONArray(Arrays.asList(objs)); 
      jsonArrayOuter.put(jsonArrayInner); 
     } 
     try { 
      jsonArrayOuter.write(writer); 
      writer.write("\n"); 
      writer.flush(); 
     } catch (JSONException je) { 
      throw new WebApplicationException(new Exception(ImplMessages.ERROR_WRITING_JSON_ARRAY(), je), 500); 
     } 
    } 
} 

Dann erstreckt ich es in ein, weil dies:

@GET 
    @Path("/{id}/search") 
    @Produces(JSON) 
    public ListWrapper search(@PathParam("id") Integer projectId) { 
     return DatabaseManager.search(projectId); 
    } 

Die Suchmethode ist eine Listwrapper mit einer Liste der Rückkehr of Object []

Hoffe das hilft jemandem :-)

Verwandte Themen