2012-05-02 30 views
4

我有一個我希望通過Jersey RESTful API公開的類。它看起來類似於這樣:在JAXB中包含Jersey JEST輸出的JSON輸出中的null元素

@XmlRootElement 
public class Data { 
    public String firstName; 
    public String lastName; 
} 

我的問題是,這些字段可以爲空,在這種情況下,現場從JSON輸出中省略。我希望所有的領域都能在場,無論其價值如何。例如,如果lastName的爲空,則JSON輸出將是:

{ 
    "firstName" : "Oleksi" 
} 

,而不是我想要的東西:

{ 
    "firstName" : "Oleksi", 
    "lastName" : null 
} 

我有一個JAXBContextResolver(ContextResolver的實現),看起來像這樣:

@Provider 
public class JAXBContextResolver implements ContextResolver<JAXBContext> { 

    // internal state 
    private final JAXBContext context;  
    private final Set<Class> types; 
    private final Class[] cTypes = { Data.class }; 


    public JAXBContextResolver() 
    throws Exception { 

     types = new HashSet(Arrays.asList(cTypes)); 
     context = new JSONJAXBContext(JSONConfiguration.natural().humanReadableFormatting(true).build(), cTypes); 
    } 

    @Override 
    public JAXBContext getContext(Class<?> objectType) { 

     return (types.contains(objectType)) ? context : null; 
    } 
} 

我一直在試圖弄清楚如何獲得期望的輸出一段時間,但我沒有運氣。我很樂意嘗試其他ContextResolvers/Serializer,但我一直無法找到一個可行的代碼,所以代碼示例會很好。

回答

10

對於EclipseLink JAXB (MOXy)的JSON綁定,正確的映射如下所示。你可以與你的供應商嘗試一下,看看它是否也將工作:

@XmlRootElement 
public class Data { 
    @XmlElement(nillable=true) 
    public String firstName; 

    @XmlElement(nillable=true) 
    public String lastName; 
} 

更多信息


UP DATE 2

的EclipseLink 2.4包括MOXyJsonProvider這是MessageBodyReader/MessageBodyWriter一個實現,它可以直接使用利用MOXY的JSON結合

UPDATE 1

以下MessageBodyReader/MessageBodyWriter可能對你更好:

import java.io.*; 
import java.lang.annotation.Annotation; 
import java.lang.reflect.*; 
import javax.xml.transform.stream.StreamSource; 

import javax.ws.rs.*; 
import javax.ws.rs.core.*; 
import javax.ws.rs.ext.*; 
import javax.xml.bind.*; 

import org.eclipse.persistence.jaxb.JAXBContextFactory; 

@Provider 
@Produces(MediaType.APPLICATION_JSON) 
@Consumes(MediaType.APPLICATION_JSON) 
public class MOXyJSONProvider implements 
    MessageBodyReader<Object>, MessageBodyWriter<Object>{ 

    @Context 
    protected Providers providers; 

    public boolean isReadable(Class<?> type, Type genericType, 
     Annotation[] annotations, MediaType mediaType) { 
     return true; 
    } 

    public Object readFrom(Class<Object> type, Type genericType, 
      Annotation[] annotations, MediaType mediaType, 
      MultivaluedMap<String, String> httpHeaders, InputStream entityStream) 
      throws IOException, WebApplicationException { 
      try { 
       Class<?> domainClass = getDomainClass(genericType); 
       Unmarshaller u = getJAXBContext(domainClass, mediaType).createUnmarshaller(); 
       u.setProperty("eclipselink.media-type", mediaType.toString()); 
       u.setProperty("eclipselink.json.include-root", false); 
       return u.unmarshal(new StreamSource(entityStream), domainClass).getValue(); 
      } catch(JAXBException jaxbException) { 
       throw new WebApplicationException(jaxbException); 
      } 
    } 

    public boolean isWriteable(Class<?> type, Type genericType, 
     Annotation[] annotations, MediaType mediaType) { 
     return true; 
    } 

    public void writeTo(Object object, Class<?> type, Type genericType, 
     Annotation[] annotations, MediaType mediaType, 
     MultivaluedMap<String, Object> httpHeaders, 
     OutputStream entityStream) throws IOException, 
     WebApplicationException { 
     try { 
      Class<?> domainClass = getDomainClass(genericType); 
      Marshaller m = getJAXBContext(domainClass, mediaType).createMarshaller(); 
      m.setProperty("eclipselink.media-type", mediaType.toString()); 
      m.setProperty("eclipselink.json.include-root", false); 
      m.marshal(object, entityStream); 
     } catch(JAXBException jaxbException) { 
      throw new WebApplicationException(jaxbException); 
     } 
    } 

    public long getSize(Object t, Class<?> type, Type genericType, 
     Annotation[] annotations, MediaType mediaType) { 
     return -1; 
    } 

    private JAXBContext getJAXBContext(Class<?> type, MediaType mediaType) 
     throws JAXBException { 
     ContextResolver<JAXBContext> resolver 
      = providers.getContextResolver(JAXBContext.class, mediaType); 
     JAXBContext jaxbContext; 
     if(null == resolver || null == (jaxbContext = resolver.getContext(type))) { 
      return JAXBContextFactory.createContext(new Class[] {type}, null); 
     } else { 
      return jaxbContext; 
     } 
    } 

    private Class<?> getDomainClass(Type genericType) { 
     if(genericType instanceof Class) { 
      return (Class<?>) genericType; 
     } else if(genericType instanceof ParameterizedType) { 
      return (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[0]; 
     } else { 
      return null; 
     } 
    } 

} 
+0

我試過這個,但我不能完全得到它的工作。您能否提供更多關於所需的其他代碼更改的詳細信息(除上面列出的內容外)。例如,我是否必須更改我的JAXBContextResolver類? – Oleksi

+0

我也在下載這個項目所需的依賴時遇到困難。我試着看這個文件無濟於事。 http://wiki.eclipse.org/EclipseLink/Maven – Oleksi

+0

下面是一個示例pom.xml:https://github.com/bdoughan/blog20110819/blob/master/pom。xml –

0

Java null是JavaScript的未定義。如果您想將Java null轉換爲JavaScript空值,則需要諮詢您的轉換庫。