11

最近、Spring バージョンを 3.1.2 から 3.2.0 にアップグレードしました。ルート要素のラップ、ObjectMapper で定義されている null 値の防止などの JSON プロパティが機能しなくなっていることがわかりました。

ここにコードスニペットがあります

<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>

問題は何ですか?任意のポインタをいただければ幸いです。

4

2 に答える 2

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:message-converter経由:

<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"}サンプルクラスを使用するときに両方が私に与える場所

デモ.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:message-converterメソッドが機能すると考えていたのは、実行するデフォルトの Bean 登録をオーバーライドする問題<mvc:annotation-driven/>( Web MVC フレームワークを参照) と、ネストされた構成の使用が推奨されている (?) ためです。

Jackson 2 のサポートにより、Jackson 1 との下位互換性の問題が発生したのではないでしょうか?

ただし、MappingJackson2HttpMessageConverter (Spring 3.1.2 および Spring 3.2 でサポート)に切り替えると、ObjectMapper 構成を変更して、null 値を書き込まず、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);
   }
}

Jackson 2 の新しいパッケージ構造へのDemo.javaスイッチ

import com.fasterxml.jackson.annotation.JsonProperty;

demo-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ドキュメントによると、この機能は v2.0 より前では非推奨であり、とにかくWRITE_NULL_PROPERTIES使用する必要があります。SerializationConfig.setSerializationInclusion()これが@SuppressWarnings("deprecation")、コードに が存在する理由だと思います。Jackson >= v2.0 では削除されたため、CustomJacksonObjectMapper.javaの例のコードが変更されました。

Spring で ObjectMapper を構成すると、代替ソリューションが提案されます。

それが役に立てば幸い!

于 2013-01-15T11:50:47.253 に答える
0

これは古い投稿ですが、似たような (もしかしたら同じかも?) 問題を段階的に解決しました。次の問題まで追跡しました(これは他の人に役立つかもしれません):

  • 追加された余分なライブラリには、Jackson 2.x への一時的な依存関係があります
  • これまでのところ、Jackson 1.x に依存していました。
  • Jackson 1.x と Jackson 2.x の間で、競合を避けるために名前空間が変更されました
  • Sprint は新しい (2.x) バージョンの採用を開始しました
  • 注釈は古い (1.x) バージョンのままでした

問題を解決するには、次のいずれかを実行できます。

  1. 2.x バージョンを再度削除します
  2. 注釈を 2.x バージョンにアップグレードします
  3. 2.x バージョンもカバーする追加の注釈を追加します

私の場合、2 つの異なるバージョンが必要であり、追加の注釈によって大きなオーバーヘッドが追加されなかったため、ソリューション 3 を使用しました。

于 2015-02-10T10:01:40.283 に答える