2012-10-03 20 views
35

Tengo un servicio web de primavera que devuelve una respuesta json. Estoy usando el ejemplo dado aquí para crear el servicio: http://www.mkyong.com/spring-mvc/spring-3-mvc-and-json-example/Spring REST Service: cómo configurar para eliminar objetos nulos en la respuesta json

El formato JSON se devuelve en es: { "name": null, "staffName": [ "KFC-Kampar", "Smith" ]}

Quiero eliminar todos los objetos nulos de la respuesta devuelta por lo que se ve así: { "staffName": [ "KFC-Kampar", "Smith"]}

he encontrado similares preguntas aquí, pero he podido obtener una solución de trabajo, por ejemplo

Configuring ObjectMapper in Spring

How to configure MappingJacksonHttpMessageConverter while using spring annotation-based configuration?

configuring the jacksonObjectMapper not working in spring mvc 3

how to configure spring mvc 3 to not return "null" object in json response?

Spring configure @ResponseBody JSON format

Jackson+Spring3.0.5 custom object mapper

Al leer estas y otras fuentes, pensé que la forma más limpia de lograr lo que quería era usar Spring 3.1 y los convertidores de mensajes que se pueden configurar dentro de la anotación mvc. Mi archivo de configuración de la primavera actualizada es:

<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:context="http://www.springframework.org/schema/context" 
xmlns:mvc="http://www.springframework.org/schema/mvc" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation=" 
    http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.1.xsd 
    http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd"> 

<context:component-scan base-package="com.mkyong.common.controller" /> 

<mvc:annotation-driven> 
    <mvc:message-converters> 
     <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> 
      <property name="prefixJson" value="true" /> 
      <property name="supportedMediaTypes" value="application/json" /> 
      <property name="objectMapper"> 
       <bean class="org.codehaus.jackson.map.ObjectMapper"> 
        <property name="serializationInclusion" value="NON_NULL"/> 
       </bean> 
      </property> 
     </bean> 
    </mvc:message-converters> 
</mvc:annotation-driven> 

La clase de servicio es el mismo que el dado en el sitio mkyong.com, excepto lo comenté a cabo el ajuste de la variable Nombre de la tienda por lo que es nula, es decir

@Controller 
@RequestMapping("/kfc/brands") 
public class JSONController { 
    @RequestMapping(value="{name}", method = RequestMethod.GET) 
    @ResponseStatus(HttpStatus.OK) 
    public @ResponseBody Shop getShopInJSON(@PathVariable String name) { 
     Shop shop = new Shop(); 
     //shop.setName(name); 
     shop.setStaffName(new String[]{name, "cronin"}); 
     return shop; 
    } 
} 

Las jarras de Jackson que estoy usando son jackson-mapper-asl 1.9.0 y jackson-core-asl 1.9.0. Estos son los únicos frascos nuevos que agregué al pom como parte del proyecto Spring-json que descargué de mkyong.com.

El proyecto se genera correctamente, pero cuando invoco el servicio a través del navegador sigo teniendo el mismo, es decir { "name": null, "staffName": [ "KFC-Kampar", "Smith"]}

¿Alguien puede decirme dónde me está yendo mal con mi configuración?

He intentado varias otras opciones, pero la única forma en que he podido devolver el json en el formato correcto es agregar el asignador de objetos al JSONController y hacer que el método "getShopInJSON" devuelva una cadena, es decir,

public @ResponseBody String getShopInJSON(@PathVariable String name) throws JsonGenerationException, JsonMappingException, IOException { 
    ObjectMapper mapper = new ObjectMapper(); 
    mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL); 

    Shop shop = new Shop(); 
    //shop.setName(name); 
    shop.setStaffName(new String[]{name, "cronin"}); 
    String test = mapper.writeValueAsString(shop); 
    return test; 
} 

Ahora bien, si invoco el servicio que esperaba obtener el es decir, { "staffName": [ "KFC-Kampar", "Cronin"]}

también he sido capaz de conseguir que funcione usando la anotación @JsonIgnore, pero esta solución no es adecuada para mí.

No entiendo por qué funciona en código pero no en la configuración, por lo que cualquier ayuda sería fantástica.

+1

Para mí Parecía primavera no está utilizando el objeto del asignador que se define en el archivo de Contex, he comprobado con el resorte de depuración está llamando al método 'setSerializationInclusion()' para el objeto mapeador definido en xml – Elbek

+1

Ya es como yo lo entiendo también. El asignador de objetos parece estar configurado correctamente, simplemente no se está utilizando en el contenedor de resorte. – mikec

Respuesta

1

He encontrado una solución mediante la configuración del contenedor Spring, pero todavía no es exactamente lo que quería.

que vuelve a ser la primavera 3.0.5, eliminado y en su lugar me cambió mi archivo de configuración para:

<bean 
    class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> 
    <property name="messageConverters"> 
     <list> 
      <bean 
       class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> 
       <property name="objectMapper" ref="jacksonObjectMapper" /> 
      </bean> 
     </list> 
    </property> 
</bean> 


<bean id="jacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper" /> 
<bean id="jacksonSerializationConfig" class="org.codehaus.jackson.map.SerializationConfig" 
    factory-bean="jacksonObjectMapper" factory-method="getSerializationConfig" /> 
<bean 
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> 
    <property name="targetObject" ref="jacksonSerializationConfig" /> 
    <property name="targetMethod" value="setSerializationInclusion" /> 
    <property name="arguments"> 
     <list> 
      <value type="org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion">NON_NULL</value> 
     </list> 
    </property> 
</bean> 

Esto es, por supuesto, similares a las respuestas dadas en otras cuestiones, por ejemplo,

configuring the jacksonObjectMapper not working in spring mvc 3

Lo importante a destacar es que mvc: anotación impulsada y AnnotationMethodHandlerAdapter no se pueden utilizar en el mismo contexto.

Todavía no puedo hacer que funcione con Spring 3.1 y mvc: aunque impulsado por anotaciones. Una solución que utiliza mvc: impulsada por anotaciones y todos los beneficios que la acompañan sería mucho mejor, creo. Si alguien pudiera mostrarme cómo hacer esto, sería genial.

5

Si está utilizando Jackson 2, el mensaje de la etiqueta convertidores es:

<mvc:annotation-driven> 
    <mvc:message-converters> 
     <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> 
      <property name="prefixJson" value="true"/> 
      <property name="supportedMediaTypes" value="application/json"/> 
      <property name="objectMapper"> 
       <bean class="com.fasterxml.jackson.databind.ObjectMapper"> 
        <property name="serializationInclusion" value="NON_NULL"/> 
       </bean> 
      </property> 
     </bean> 
    </mvc:message-converters> 
</mvc:annotation-driven> 
50

Desde Jackson 2.0 se puede utilizar JsonInclude

@JsonInclude(Include.NON_NULL) 
public class Shop { 
    //... 
} 
2

Desde la versión 1.6 tenemos nueva anotación JsonSerialize (en la versión 1.9.9 por ejemplo).

Ejemplo:

@JsonSerialize(include=Inclusion.NON_NULL) 
public class Test{ 
... 
} 

valor por defecto es siempre.

En versiones anteriores puede usar JsonWriteNullProperties, que está en desuso en las nuevas versiones. Ejemplo:

@JsonWriteNullProperties(false) 
public class Test{ 
    ... 
} 
+0

'' @JsonSerialize (include = Inclusion.NON_NULL) '' obsoleto – cheloncio

5

A partir de Jackson 2.0, @JsonSerialize(include = xxx) ha sido desaprobado en favor de @JsonInclude

3

Para todos ustedes que no son XML de configuración gente:

ObjectMapper objMapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL); 
HttpMessageConverter msgConverter = new MappingJackson2HttpMessageConverter(objMapper); 
restTemplate.setMessageConverters(Collections.singletonList(msgConverter)); 
2
@JsonSerialize(include=JsonSerialize.Inclusion.NON_EMPTY) 
public class Shop { 
    //... 
} 

Esta voluntad eliminar objetos vacíos y nulos

19

Como se está utilizando Jackson, debe configurarlo como propiedad de Jackson.En el caso de los servicios de la primavera de arranque REST, hay que configurarlo en application.properties:

spring.jackson.default-property-inclusion=NON_NULL 

source

+2

desafortunadamente, un moderador eliminó mi respuesta diciendo que esas eran preguntas repetidas. Pero él es un chico de Python y tal vez no podía ver esas eran diferentes preguntas de Java Spring (una para Spring MVC, otra para Spring REST). Él borró el que está en la pregunta más importante. Por cierto, no hay manera de tailer. Las respuestas son iguales. La biblioteca es la misma (Jackson). Lo intentaré de nuevo, para ayudar a la comunidad. –

+12

El nombre de la propiedad ha cambiado a 'spring.jackson.default-property-inclusion = NON_NULL'. ¡Funciona bien! – Miguel

Cuestiones relacionadas