2013-01-15 46 views
11

我最近將我的Spring版本從3.1.2升級到3.2.0。我發現像wrap wrap元素這樣的JSON屬性,防止在ObjectMapper中定義的null值不再工作。Spring MVC 3.2和JSON ObjectMapper問題

這裏是代碼片段

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" /> 
    <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"> 
    <property name="favorPathExtension" value="true" /> 
    <property name="ignoreAcceptHeader" value="false" /> 
    <property name="mediaTypes" > 
     <value> 
      json=application/json 
      xml=application/xml 
     </value> 
    </property> 
</bean> 

和JSON轉換器

<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> 
    <property name="objectMapper" ref="customJacksonObjectMapper"/> 
    <property name="supportedMediaTypes" value="application/json"/> 
</bean> 

對象映射器代碼

public class CustomJacksonObjectMapper extends ObjectMapper { 

@SuppressWarnings("deprecation") 
public CustomJacksonObjectMapper() { 
    super(); 
    final AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(); 

    this.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.UNWRAP_ROOT_VALUE, true); 
    this.configure(org.codehaus.jackson.map.SerializationConfig.Feature.WRAP_ROOT_VALUE, true); 

    this.configure(org.codehaus.jackson.map.SerializationConfig.Feature.WRITE_NULL_PROPERTIES, false); 

    this.setDeserializationConfig(this.getDeserializationConfig().withAnnotationIntrospector(introspector)); 
    this.setSerializationConfig(this.getSerializationConfig().withAnnotationIntrospector(introspector)); 

    } 
} 

傑克遜版本

<dependency> 
     <groupId>org.codehaus.jackson</groupId> 
     <artifactId>jackson-xc</artifactId> 
     <version>1.9.7</version> 
    </dependency> 

可能是什麼問題?任何指針讚賞。

+0

你確定使用了'CustomJacksonObjectMapper'嗎? – axtavt

回答

14

聲明:我無法確定問題代碼爲什麼不起作用,但我可以重現該問題。這個答案確實提供了一種適用於我的替代方法。

可能是一個錯誤,因爲我可以用這兩個具有明確的配置重現問題:

<bean id="jacksonObjectMapper" class="com.demo.CustomJacksonObjectMapper"/> 

<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> 
    <property name="objectMapper" ref="jacksonObjectMapper"/> 
    <property name="supportedMediaTypes" value="application/json"/> 
</bean> 

,並通過MVC:信息轉換器

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"> 
    <mvc:message-converters> 
     <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> 
      <property name="objectMapper" ref="jacksonObjectMapper" /> 
     </bean> 
    </mvc:message-converters> 
</mvc:annotation-driven> 

當使用示例類時,兩者都給我{"foo":null,"bar":"bar"}

Demo.java

import org.springframework.stereotype.Controller; 
import org.springframework.web.bind.annotation.*; 
import org.codehaus.jackson.annotate.JsonProperty; 

@Controller 
@RequestMapping("/data") 
public class Data { 
    @RequestMapping 
    @ResponseBody 
    public Dummy dataIndex() { 
     return new Dummy(); 
    } 

    public class Dummy { 
     String foo = null; 
     @JsonProperty 
     public String foo() { 
      return foo; 
     } 
     String bar = "bar"; 
     @JsonProperty 
     public String bar() { 
      return bar; 
     } 
    } 
} 

不過,我已經想好了MVC:信息轉換器法會的工作,只是因爲我已經看到覆蓋默認豆登記事項,<mvc:annotation-driven/>執行(見Web MVC Framework)和使用嵌套配置是首選(?)。

也許Jackson 2 support導致了Jackson 1的一些向後兼容性問題?

然而,切換到MappingJackson2HttpMessageConverter(在Spring 3.1.2和Spring 3.2的支持),我上午能夠改變ObjectMapper配置不寫空值,敷JSON輸出...... 只有當使用<mvc:message-converters/>內的配置!

我得到{"Dummy":{"bar":"bar"}}有以下變化:

的pom.xml

<dependency> 
    <groupId>com.fasterxml.jackson.core</groupId> 
    <artifactId>jackson-core</artifactId> 
    <version>2.1.0</version> 
</dependency> 
<dependency> 
    <groupId>com.fasterxml.jackson.core</groupId> 
    <artifactId>jackson-databind</artifactId> 
    <version>2.1.0</version> 
</dependency> 
<dependency> 
    <groupId>com.fasterxml.jackson.core</groupId> 
    <artifactId>jackson-annotations</artifactId> 
    <version>2.1.0</version> 
</dependency> 

CustomJacksonObjectMapper。的java

import com.fasterxml.jackson.databind.ObjectMapper; 
import com.fasterxml.jackson.databind.DeserializationFeature; 
import com.fasterxml.jackson.databind.SerializationFeature; 
import static com.fasterxml.jackson.annotation.JsonInclude.*; 

public class CustomJacksonObjectMapper extends ObjectMapper { 

public CustomJacksonObjectMapper() { 
    super(); 
    this.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true); 
    this.configure(SerializationFeature.WRAP_ROOT_VALUE, true); 
    this.setSerializationInclusion(Include.NON_NULL); 
    } 
} 

Demo.java切換到新的封裝結構爲傑克遜2

import com.fasterxml.jackson.annotation.JsonProperty; 

演示servlet.xml中

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"> 
    <mvc:message-converters> 
     <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> 
      <property name="objectMapper" ref="jacksonObjectMapper" /> 
     </bean> 
    </mvc:message-converters> 
</mvc:annotation-driven> 

最後,根據SerializationConfig.Feature文檔,WRITE_NULL_PROPERTIES功能已被棄用< v2.0,無論如何你應該使用SerializationConfig.setSerializationInclusion()。我認爲這就是你的代碼中存在@SuppressWarnings("deprecation")的原因。在Jackson> = v2.0中,它已被刪除,因此代碼更改爲CustomJacksonObjectMapper.java示例。

Configuring ObjectMapper in Spring提出了一種替代解決方案。

希望它有幫助!

+0

非常感謝您花時間在短時間內回覆。這對我有效。還特別感謝stackoverflow.com提供這個美妙的平臺,分享這些東西,它的時間爲我提供了方式,我可以...... – spal

+0

樂於幫助:-)如果任何人都可以確定爲什麼它是傑克遜1,我很想知道爲什麼!如果我有時間,我會嘗試調試Spring。 – andyb

+0

@andyb我試過這個解決方案,但當我嘗試啓動Tomcat時,出現'java.lang.ClassNotFoundException:com.demo.CustomJacksonObjectMapper'異常。 你有什麼想法嗎? 非常感謝! – Pmt

0

即使這是一箇舊的帖子,我分階段類似(甚至可能是相同的?)的問題。我跟蹤它到了以下問題(這可能幫助他人):

  • 加入一個額外的圖書館對傑克遜2.x的短暫依賴
  • 到目前爲止,我們對傑克遜1的依賴。 X
  • 傑克遜1.x和傑克遜之間的2.X的命名空間改爲避免衝突
  • Sprint公司開始拿起更新(2.X)版本
  • 註釋仍然老(1。 x)版本

爲了解決這個問題,我可以:

  1. 刪除2.x版再次
  2. 升級註釋2.x版
  3. 添加額外的註釋也包括在2.x版本

在我的情況我去了解決方案3,因爲我們需要兩個不同的版本和額外的註釋並沒有增加大的開銷。