2009-07-17 15 views
8

Pracuję nad projektem, który używa oprogramowania Jersey do konwersji obiektów na JSON. Chciałbym, aby móc pisać zagnieżdżonych list tak:Jak mogę zagnieżdżać listy zagnieżdżone jako JSON przy użyciu Jersey? Otrzymuję tablicę wartości null lub tablicę jednoskładnikowych słowników zawierających tablicę

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

Przedmiotem Chciałbym przekonwertować pierwszy reprezentował dane jako < LinkedList LinkedList < <String> > > i wyobraziłem Jersey po prostu postąpiłby słusznie. Powyższe było wyjście w postaci listy null:

{"data":[null, null]} 

Po przeczytaniu że zagnieżdżone obiekty muszą być opakowane, próbowałem następujące:

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

Ten kod wyjścia, co poniżej, który jest bliżej do tego, co Chcę:

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

Chcę pierwsze dane się lista list, nie lista słowników jednoelementowych. Jak to osiągnąć?

Oto mój 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; 
    } 
} 

Odpowiedz

5

Czy próbowałeś Jersey-json ??

Dodaj Jersey-json na ścieżce klas (lub swoimi zależnościami maven)

Następnie użyj tego:

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

} 

Trzeba tylko coś takiego w swoim ressources (zakładając DetailProduit to Twój obiekt chcesz serializacji i że DetailProduit.java jest JAXB znakowany aw package.of.your.model)

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

Ok, właśnie pomyślałem, że twoja sprawa była bardziej skomplikowana niż ja ... – Arnaudweb

0

Wiem qustion jest dość stary, ale natknąłem się na podobny problem, ale chciałem, aby uczynić listy tablic ie.'List' powodu wyniku z db, który dostałem od jpa i zapytanie nativ bez użycia Encji.

ten sposób Rozwiązałem go:

Pierwszy Utworzony ListWrapper.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); 
    } 
} 

A potem stworzył klasę rozciągający 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); 
     } 
    } 
} 

Potem używając go w sposób jak poniżej:

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

Metoda wyszukiwania jest zwrócenie Listwrapper z listy Obiektu []

Mam nadzieję, że to pomoże komuś :-)