2011-07-27 51 views
26

實施例JSON(註釋字符串已經尾部空格):可以將Jackson配置爲修剪所有字符串屬性的前導/後綴空白嗎?

{ "aNumber": 0, "aString": "string " } 

理想地,deserialised實例將具有ASTRING屬性與「串」(即沒有尾部空格)的值。這似乎喜歡的事,可能是支持的,但(在DeserializationConfig.Feature例如)我找不到它。

我們在使用Spring MVC 3.X所以基於Spring的解決方案也將被罰款。

我試圖基於在forum post建議配置Spring的WebDataBinder但它似乎並沒有使用傑克遜的消息變換時的工作:

@InitBinder 
public void initBinder(WebDataBinder binder) 
{ 
    binder.registerCustomEditor(String.class, new StringTrimmerEditor(" \t\r\n\f", true)); 
} 
+0

您是否100%確定空格不在實際值中?因爲我從未見過傑克遜這樣做。或者你是否在說你傳給傑克遜的課程有意識地留下了這些尾隨空間,並且你想讓傑克遜爲你刪除它? –

+1

@matt:我認爲這很清楚地表明數據有來自源頭的空格,他想配置Jackson去除反序列化的尾部空格。 –

+0

這是正確的,我們沒有任何理由在傳入的JSON消息中保留尾隨(或前導)空白。 – penfold

回答

13

隨着custom deserializer,你可以做到以下幾點:

<your bean> 
@JsonDeserialize(using=WhiteSpaceRemovalSerializer.class) 
public void setAString(String aString) { 
    // body 
} 

<somewhere> 
public class WhiteSpaceRemovalDeserializer extends JsonDeserializer<String> { 
    @Override 
    public String deserialize(JsonParser jp, DeserializationContext ctxt) { 
     // This is where you can deserialize your value the way you want. 
     // Don't know if the following expression is correct, this is just an idea. 
     return jp.getCurrentToken().asText().trim(); 
    } 
} 

這種解決方案並不意味着這個bean屬性始終被序列這種方式,你將有標註要反序列化這樣每個屬性。

+0

謝謝,雖然我認爲_this.aString = aString.trim()_可能更容易:-)但願它將成爲未來版本的一個功能。 – penfold

+0

雖然這很容易,但註釋可以確保只有在通過JSON反序列化創建bean時纔會發生修剪:) – DCKing

+1

@DCKing:爲什麼不只是通過Module interface註冊您的自定義解串器?當Jackson僅用於REST風格的Web服務時,我無法想象在典型的Spring應用程序中會有什麼不好的後果,對嗎? –

11

註釋@JsonDeserialize的問題是,你必須始終記得把它的制定者。 爲了讓全球的 「一勞永逸」 與Spring MVC,我做了下面的步驟:

的pom.xml:

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

創建自定義ObjectMapper:

package com.mycompany; 

    import java.io.IOException; 
    import org.apache.commons.lang3.StringUtils; 
    import com.fasterxml.jackson.core.JsonParser; 
    import com.fasterxml.jackson.core.JsonProcessingException; 
    import com.fasterxml.jackson.databind.DeserializationContext; 
    import com.fasterxml.jackson.databind.ObjectMapper; 
    import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer; 
    import com.fasterxml.jackson.databind.module.SimpleModule; 

    public class MyObjectMapper extends ObjectMapper { 

     public MyObjectMapper() { 
      registerModule(new MyModule()); 
     } 
    } 

    class MyModule extends SimpleModule { 

     public MyModule() { 
      addDeserializer(String.class, new StdScalarDeserializer<String> (String.class) { 
       @Override 
       public String deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, 
        JsonProcessingException { 
        return StringUtils.trim(jp.getValueAsString()); 
       } 
      }); 
     } 
    } 

更新Spring的servlet的上下文.xml:

<bean id="objectMapper" class="com.mycompany.MyObjectMapper" /> 

    <mvc:annotation-driven> 
     <mvc:message-converters> 
      <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> 
       <property name="objectMapper" ref="objectMapper" /> 
      </bean> 
     </mvc:message-converters> 
    </mvc:annotation-driven> 
+0

這似乎是一個很好的全局解決方案,很容易使用自定義的ObjectMapper添加我的Spring Boot應用程序:我只是沿着這些行定義並註冊了「StringTrimmerModule」。 (儘管我更喜歡簡單的舊'String.trim()'爲非空值而不是Commons StringUtils。) – Jonik

+0

請注意,如果使用[afterburner](https://github.com/FasterXML/jackson-module-afterburner)那麼這將不會像加力燃燒器優化那些默認的反序列化器那樣工作。如果是這種情況,那麼我想你被卡在@JsonDeserialize? – jontejj

+0

此解決方案對不屬於字符串的JSON屬性的影響如數字或布爾型 –

15

Spring Boot用戶的簡單解決方案,只需添加walv的Simp leModule擴展您的應用程序上下文:

package com.example; 

import com.fasterxml.jackson.core.JsonParser; 
import com.fasterxml.jackson.core.JsonProcessingException; 
import com.fasterxml.jackson.databind.DeserializationContext; 
import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer; 
import com.fasterxml.jackson.databind.module.SimpleModule; 
import org.springframework.stereotype.Component; 

import java.io.IOException; 

@Component 
public class StringTrimModule extends SimpleModule { 

    public StringTrimModule() { 
     addDeserializer(String.class, new StdScalarDeserializer<String>(String.class) { 
      @Override 
      public String deserialize(JsonParser jsonParser, DeserializationContext ctx) throws IOException, 
        JsonProcessingException { 
       return jsonParser.getValueAsString().trim(); 
      } 
     }); 
    } 
} 

另一種方式來定製傑克遜是類型com.fasterxml.jackson.databind.Module的豆子添加到您的環境。他們將被註冊到ObjectMapper類型的每一個bean中,當你嚮應用程序添加新特性時,它提供了一個全局機制來爲自定義模塊做貢獻。

http://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html#howto-customize-the-jackson-objectmapper

,如果你不使用春天開機,你必須註冊StringTrimModule自己(你不需要用@Component註釋吧)

<bean class="org.springframework.http.converter.json.Jackson2Objec‌​tMapperFactoryBean"> 
    <property name="modulesToInstall" value="com.example.StringTrimModule"/> 
</bean 
0

春季啓動,我們只需要創建一個自定義解串器documented in the manual

,以下是我的Groovy代碼,但隨時去適應它在Java中的工作。

import com.fasterxml.jackson.core.JsonParser 
import com.fasterxml.jackson.databind.DeserializationContext 
import com.fasterxml.jackson.databind.JsonDeserializer 
import org.springframework.boot.jackson.JsonComponent 

import static com.fasterxml.jackson.core.JsonToken.VALUE_STRING 

@JsonComponent 
class TrimmingJsonDeserializer extends JsonDeserializer<String> { 

    @Override 
    String deserialize(JsonParser parser, DeserializationContext context) { 
     parser.hasToken(VALUE_STRING) ? parser.text?.trim() : null 
    } 
}