web-dev-qa-db-ja.com

JSONデシリアライザーをSpringで記述する、または拡張する正しい方法

SpringでカスタムJSONデシリアライザーを作成しようとしています。フィールドのほとんどの部分でデフォルトのシリアライザーを使用し、いくつかのプロパティではカスタムのデシリアライザーを使用します。出来ますか?プロパティの大部分が値であるため、私はこの方法を試しています。したがって、これらの場合、Jacksonにデフォルトのデシリアライザーを使用させることができます。しかし、いくつかのプロパティは参照であるため、カスタムデシリアライザーでは、データベースに参照名を照会し、データベースから参照値を取得する必要があります。

必要に応じていくつかのコードを示します。

51
gc5

私はよく検索しましたが、これまでに見つけた最良の方法はこれです 記事

シリアル化するクラス

package net.sghill.example;

import net.sghill.example.UserDeserializer
import net.sghill.example.UserSerializer
import org.codehaus.jackson.map.annotate.JsonDeserialize;
import org.codehaus.jackson.map.annotate.JsonSerialize;

@JsonDeserialize(using = UserDeserializer.class)
public class User {
    private ObjectId id;
    private String   username;
    private String   password;

    public User(ObjectId id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    public ObjectId getId()       { return id; }
    public String   getUsername() { return username; }
    public String   getPassword() { return password; }
}

デシリアライザクラス

package net.sghill.example;

import net.sghill.example.User;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.ObjectCodec;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;

import Java.io.IOException;

public class UserDeserializer extends JsonDeserializer<User> {

    @Override
    public User deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        ObjectCodec oc = jsonParser.getCodec();
        JsonNode node = oc.readTree(jsonParser);
        return new User(null, node.get("username").getTextValue(), node.get("password").getTextValue());
    }
}

編集:または、com.fasterxml.jackson.databind.JsonDeserializerの新しいバージョンを使用する この記事 を見ることができます。

78
gc5

私は@Autowire Spring管理のサービスをDeserializerに追加します。誰かがシリアライザー/デシリアライザーを呼び出すときにnew演算子を使用してジャクソンに私をだましました。これは、私のDeserializerのJacksonのインスタンスの自動配線がないことを意味しました。 @AutowireDeserializerへのサービスクラス:

context.xml

<mvc:annotation-driven>
  <mvc:message-converters>
    <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
      <property name="objectMapper" ref="objectMapper" />
    </bean>
  </mvc:message-converters>
</mvc>
<bean id="objectMapper" class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
    <!-- Add deserializers that require autowiring -->
    <property name="deserializersByType">
        <map key-type="Java.lang.Class">
            <entry key="com.acme.Anchor">
                <bean class="com.acme.AnchorDeserializer" />
            </entry>
        </map>
    </property>
</bean>

DeserializerがSpring管理のBeanになったので、自動配線が機能します!

AnchorDeserializer.Java

public class AnchorDeserializer extends JsonDeserializer<Anchor> {
    @Autowired
    private AnchorService anchorService;
    public Anchor deserialize(JsonParser parser, DeserializationContext context)
             throws IOException, JsonProcessingException {
        // Do stuff
    }
}

AnchorService.Java

@Service
public class AnchorService {}

更新:私がこれを書いたとき、元の答えは私にとってはうまくいきましたが、@ xi.linの応答はまさに必要なものです。素敵な発見!

9
Beez

Spring MVC 4.2.1.RELEASEでは、デシリアライザーが機能するために、以下の新しいJackson2依存関係を使用する必要があります。

これを使用しないでください

<dependency>  
            <groupId>org.codehaus.jackson</groupId>  
            <artifactId>jackson-mapper-asl</artifactId>  
            <version>1.9.12</version>  
        </dependency>  

代わりにこれを使用してください。

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

また、com.fasterxml.jackson.databind.JsonDeserializerからのクラスではなく、com.fasterxml.jackson.databind.annotation.JsonDeserializeおよびorg.codehaus.jacksonを逆シリアル化に使用します

1
VimalKumar