web-dev-qa-db-ja.com

Spring、Jackson、Customization(CustomDeserializerなど)

まだSpringに少し慣れていないので、 問題 に遭遇したため、Jackson用のカスタムデシリアライザーを実装する必要があります。手順は小さな チュートリアル で説明されていますが、私はSpringで立ち往生しています。わからない、どこ

 ObjectMapper mapper = new ObjectMapper();

springでは、MVCは、jsonがコントローラークラスのメソッドによって逆シリアル化されるときに実行されます。したがって、デフォルトのデシリアライザーをカスタムデシリアライザーに置き換えるにはどうすればよいかわかりません。

どんな提案でも大歓迎です。

21
Ta Sas

春にジャクソンをどのように使用しているかは言わないので、_<mvc:annotation-driven/>_と_@RequestBody_および/または_@ResponseBody_アノテーションを使用していると仮定します。

_<mvc:annotation-driven/>_が行うことの1つは、マーシャリングを処理するAnnotationMethodHandlerAdapterを含む多数の事前構成されたHttpMessageConverterBeanが付属するMappingJacksonHttpMessageConverterBeanを登録することです。ジャクソン注釈付きモデルクラスとの間。

現在、MappingJacksonHttpMessageConverterにはsetObjectMapper()メソッドがあり、デフォルトのObjectMapperをオーバーライドできます。ただし、MappingJacksonHttpMessageConverterは_<mvc:annotation-driven/>_によって舞台裏で作成されるため、アクセスできません。

ただし、_<mvc:annotation-driven/>_は便利なショートカットです。独自のAnnotationMethodHandlerAdapter Beanを宣言し、(MappingJacksonHttpMessageConverterプロパティを介して)独自のmessageConverters Beanを注入し、独自にカスタマイズしたObjectMapperそれに。

次に、カスタムObjectMapperを作成する方法に問題があります。これは、Springにあまり適したクラスではないためです。 FactoryBeanの独自の単純な実装 を作成することをお勧めします。

したがって、次のような結果になります。

_<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
   <property name="messageConverters">
      <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
         <property name="objectMapper">
            <bean class="com.x.MyObjectMapperFactoryBean"/>
         </property>
      </bean>
   </property>
</bean>
_
19
skaffman

Spring 3.1でこれを行う新しい方法:
http://magicmonster.com/kb/prg/Java/spring/webmvc/mvc_spring_config_namespace.html

http://blog.springsource.org/2011/02/21/spring-3-1-m1-mvc-namespace-enhancements-and-configuration/

次のようなことができます。

<mvc:annotation-driven>
      <mvc:message-converters>
          <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
              <property name="objectMapper" ref="customObjectMapper"/>
          </bean>
      </mvc:message-converters>
  </mvc:annotation-driven>
7
Ryan Walls

Rakeshによって参照されるソリューションは、Spring MVC 3.0で機能する可能性がありますが、3.1ではMVCインフラストラクチャの一部が機能します 変更されています 。その結果、アプリケーションコンテキストにAnnotationMethodHandlerAdapter Beanが登録されていない可能性があり、初期化時にBeanCreationExceptionになってしまいます。

Spring MVC 3.1の場合、mvc:annotation-driven要素は RequestMappingHandlerAdapter を作成するため、代わりにそのタイプを自動配線する必要があります。登録されたHttpMessageConvertersのリストへのアクセスを引き続き提供し、MappingJacksonHttpMessageConverterでObjectMapperプロパティを設定できるようにします。これには、init内でのわずかな変更も必要です。 HttpMessageConverters参照のタイプへのメソッド。

更新されたクラスは次のようになります。

@Component
public class JacksonFix {
    private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
    private CustomObjectMapper objectMapper;

    @PostConstruct
    public void init() {
        List<HttpMessageConverter<?>> messageConverters = requestMappingHandlerAdapter.getMessageConverters();
        for (HttpMessageConverter<?> messageConverter : messageConverters) {
            if (messageConverter instanceof MappingJacksonHttpMessageConverter) {
                MappingJacksonHttpMessageConverter m = (MappingJacksonHttpMessageConverter) messageConverter;
                m.setObjectMapper(objectMapper);
            }
        }
    }

    // this will exist due to the <mvc:annotation-driven/> bean
    @Autowired
    public void setRequestMappingHandlerAdapter(RequestMappingHandlerAdapter requestMappingHandlerAdapter) {
        this.requestMappingHandlerAdapter = requestMappingHandlerAdapter;
    }

    @Autowired
    public void setObjectMapper(CustomObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }
}

[〜#〜] update [〜#〜]:Spring 3.1で行う最も簡単なことは、いくつかの構成を追加することです。 MVC構成:

<mvc:annotation-driven conversion-service="applicationConversionService">
    <mvc:message-converters register-defaults="true">
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
            <property name="objectMapper" ref="customObjectMapper" />
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

これにより、デフォルトのHttpMessageConverters(register-defaults="true"のためにまだ存在している)の前に、カスタムObjectMapperを使用してMappingJacksonHttpMessageConverterの新しいインスタンスが追加されます。

5
kylesm

私の場合(Spring3.2.4およびJackson2.3.1)、カスタムシリアライザーのXML構成:

_<mvc:annotation-driven>
    <mvc:message-converters register-defaults="false">
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper">
                <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                    <property name="serializers">
                        <array>
                            <bean class="com.example.business.serializer.json.CustomObjectSerializer"/>
                        </array>
                    </property>
                </bean>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>
_

説明のつかない方法で、何かによってデフォルトに上書きされました。

これは私のために働いた:

CustomObject.Java

_@JsonSerialize(using = CustomObjectSerializer.class)
public class CustomObject {

    private Long value;

    public Long getValue() {
        return value;
    }

    public void setValue(Long value) {
        this.value = value;
    }
}
_

CustomObjectSerializer.Java

_public class CustomObjectSerializer extends JsonSerializer<CustomObject> {

    @Override
    public void serialize(CustomObject value, JsonGenerator jgen,
        SerializerProvider provider) throws IOException,JsonProcessingException {
        jgen.writeStartObject();
        jgen.writeNumberField("y", value.getValue());
        jgen.writeEndObject();
    }

    @Override
    public Class<CustomObject> handledType() {
        return CustomObject.class;
    }
}
_

私のソリューションでは、XML構成(<mvc:message-converters>(...)</mvc:message-converters>)は必要ありません。

2
user11153

MappingJacksonHttpMessageConverter状態の春のドキュメント:

2.4.5 MappingJacksonHttpMessageConverter

JacksonJSONプロセッサのObjectMapperを使用してJSONを読み書きできるHttpMessageConverter実装。 JSONマッピングは、Jacksonが提供する注釈を使用して、必要に応じてカスタマイズできます。さらに制御が必要な場合は、特定のタイプにカスタムJSONシリアライザー/デシリアライザーを提供する必要がある場合に備えて、ObjectMapperプロパティを介してカスタムObjectMapperを挿入できます。デフォルトでは、このコンバーターは(application/json)をサポートします。

ObjectMapperへのアクセスを自動配線して、その動作を変更することはできませんか?

0
Bruce Edge

Spring MVCをもっとよく知っていればいいのですが、JerseyやRESTeasyのようなJax-RS実装では、プロバイダーを登録します。多分春は似たようなことをしますか?

0
StaxMan