JSONの例(文字列の末尾にスペースがあることに注意してください):
{ "aNumber": 0, "aString": "string " }
理想的には、デシリアライズされたインスタンスには、aStringプロパティがあり、値が "string"(つまり、末尾のスペースなし)。これはおそらくサポートされているように見えますが、見つかりません(例:DeserializationConfig.Feature)。
Spring MVC 3.xを使用しているため、Springベースのソリューションでも問題ありません。
フォーラムポスト の提案に基づいてSpringのWebDataBinderを構成しようとしましたが、Jacksonメッセージコンバーターを使用すると機能しないようです。
@InitBinder
public void initBinder( WebDataBinder binder )
{
binder.registerCustomEditor( String.class, new StringTrimmerEditor( " \t\r\n\f", true ) );
}
カスタムデシリアライザー を使用すると、次のことができます。
<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属性が常にこの方法でシリアル化されることを意味し、この方法で逆シリアル化するすべての属性に注釈を付ける必要があります。
Spring Bootユーザー向けの簡単なソリューションは、そのwalvのSimpleModule拡張機能をアプリケーションコンテキストに追加するだけです。
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();
}
});
}
}
Jacksonをカスタマイズするもう1つの方法は、com.fasterxml.jackson.databind.ModuleタイプのBeanをコンテキストに追加することです。これらはObjectMapperタイプのすべてのBeanに登録され、アプリケーションに新しい機能を追加するときにカスタムモジュールを提供するためのグローバルメカニズムを提供します。
spring Bootを使用している場合ではない場合は、StringTrimModuleを自分で登録する必要があります(@Componentで注釈する必要はありません)
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="modulesToInstall" value="com.example.StringTrimModule"/>
</bean
アノテーション@JsonDeserializeの問題は、セッターに置くことを常に覚えておかなければならないことです。 Spring MVCでグローバルに「1回限り」を実現するために、次のステップを実行しました。
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-context.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>
Spring Bootの場合、カスタムのデシリアライザを マニュアルに記載されている として作成する必要があります。
以下は私の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
}
}
com.fasterxml.jackson.dataformat
pom.xml
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-csv</artifactId>
<version>2.5.3</version>
</dependency>
CsvUtil.Java
CsvSchema bootstrapSchema = CsvSchema.emptySchema().withHeader().sortedBy();
CsvMapper mapper = new CsvMapper();
mapper.enable(CsvParser.Feature.TRIM_SPACES);
InputStream inputStream = ResourceUtils.getURL(fileName).openStream();
MappingIterator<T> readValues =
mapper.readerFor(type).with(bootstrapSchema).readValues(inputStream);
デフォルトのStringDeserializerは、サードパーティのライブラリで使用できる特定のケース( here および here を参照)をすでに処理しているため、拡張する方が良いと思います。以下はSpring Bootの設定です。
@JsonComponent
public class StringDeserializer extends com.fasterxml.jackson.databind.deser.std.StringDeserializer {
@Override
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String value = super.deserialize(p, ctxt);
return value != null ? value.trim() : null;
}
}