当前位置: 首页 > 面试题库 >

使用JAXB在Jersey RESTful API的JSON输出中包括空元素

秦景福
2023-03-14
问题内容

我有一个要通过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<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 /
Serializers,但我一直找不到能起作用的代码,因此代码示例将是不错的选择。


问题答案:

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

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

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

想要查询更多的信息

  • http://blog.bdoughan.com/2012/04/binding-to-json-xml-handling-null.html
  • http://blog.bdoughan.com/2012/05/moxy-as-your-jax-rs-json-provider.html

更新2

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

  • http://blog.bdoughan.com/2012/05/moxy-as-your-jax-rs-json-provider.html

更新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;
        }
    }

}


 类似资料:
  • 问题内容: 在1.6.0_16 JDK上工作时,我使用Apache CXF 2.5.2从WSDL生成了存根类,Apache CXF 2.5.2使用了最新的jaxb- api 2.2。我知道可以使用jaxb-api 2.1,但是为了避免兼容性问题,我宁愿使用当前版本。由于我的JDK具有jaxb 2.1,因此构建失败并显示以下消息: 因此,我尝试使用以下依赖项使Maven包括最新的jaxb api和i

  • 问题内容: 和服务: 我的web.xml: 如果我将MediaType.APPLICATION_XML设置为Produces注释,则所有这些工作都可以进行。但是对于JSON,我得到以下异常: 严重:映射的响应异常:500(内部服务器错误)javax.ws.rs.WebApplicationException:com.sun.jersey.api.MessageException:Java类java

  • 问题内容: 我需要在jaxb中将空值显示为空元素。我正在使用jaxb的moxy实现。我找到了这个选项 是否可以在类级别应用任何类似的扩展(对于其中定义的所有元素) 问题答案: 我强烈建议使用不存在节点或使用属性来表示。这与模式验证(即或不是有效的type元素)一起使用时效果最佳。但是,如果不能这样做,那么可以完成用例: 标准JAXB行为 使用标准的API,你可以控制NULL是表示为不存在的节点或与

  • 我有两个XSD,其中一个XSD包含一个元素,该元素可以包含第二个XSD中的元素。基本上,XSD1有一个元素“etta”,它可以包含XSD2中的任何元素。 我使用xjc生成类,当它被反序列化时,元元素将XSD2中的元素作为JAXBElements包含,而不是XSD2中生成的实际类。我在我的程序中包含了这两组类,包信息是正确的。 这就是我定义XSD的方式。我想问题在于我的“任何”元素。 因此,基本上我

  • 我正在用java中的jackson构建一个json体。它会像下面这样 基于不同的 REST URI,json 主体必须忽略某些字段或元素。如何使用杰克逊忽略上述 json 正文中的“学生”部分?当我忽略它时,我应该只能得到 但我得到它如下,这是不正确的- 我有两个带有getters和setters的类,一个作为主语,另一个作为学生。我尝试使用@JsonIgnore,但是它忽略了所有的URI,这是我

  • 问题内容: 我该如何转: 到这个: 或者更确切地说,是否有任何有用的资源可供阅读,以便能够生成该JSON输出?所以我知道我需要将我的数据“转换”为正确的数据结构。之后,就像 谢谢 问题答案: 使用json库。 然后使用以下方法转换数据: 并致电: