使用JAXB在Jersey RESTful API的JSON输出中包含null元素

我有一个类,我想通过Jersey RESTful API公开。 它看起来类似于:

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

我的问题是这些字段可能为null,在这种情况下,字段从JSON输出中省略。 我希望所有领域都存在,无论它们的价值如何。 例如,如果lastName为null,则JSON输出将为:

 { "firstName" : "Oleksi" } 

而不是我想要的:

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

我有一个JAXBContextResolver(ContextResolver的实现),如下所示:

 @Provider public class JAXBContextResolver implements ContextResolver { // internal state private final JAXBContext context; private final Set 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 / Serializers,但我找不到一个有效的,所以代码示例会很好。

对于EclipseLink JAXB(MOXy)的JSON绑定,正确的映射如下。 您可以尝试与您的提供商一起查看它是否也可以:

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

了解更多信息


更新2

EclipseLink 2.4包含MOXyJsonProvider ,它是MessageBodyReader / MessageBodyWriter一个实现,您可以直接使用它来利用MOXy的JSON绑定

更新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, MessageBodyWriter{ @Context protected Providers providers; public boolean isReadable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { return true; } public Object readFrom(Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap 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 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 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; } } } 

Java null是JavaScript未定义的。 如果要将Java null转换为JavaScript null,则需要咨询转换库。