0

ジェネリック コレクション タイプごとに異なるシリアライザを使用するように jackson に指示するにはどうすればよいですか。CustomProductsSerializer と CustomClientsSerializer があります

    public class ProductsListSerializer extends JsonSerializer<List<Products>>{

    // logic to insert __metadata , __count into json
    public void serialize(List<Products> value, JsonGenerator jgen, SerializerProvider provider) {
     .... .... .... 
     }
    // always returns ArrayList.class 
    public Class<List<Instrument>> handledType() {
    Class c = var.getClass();
    return c;
    }
    }


    public class CustomClientsSerializer extends JsonSerializer<List<Clients>>{

    // logic to insert __metadata , __count into json
    public void serialize(List<Clients> value, JsonGenerator jgen, SerializerProvider provider){
     .... .... .... 
     }
     .... .... .... 
    // always returns ArrayList.class 
    public Class<List<Clients>> handledType() {
    Class c = var.getClass();
    return c;
    }
    }

SimpleModule を使用して両方のシリアライザーを登録しました。問題は、handledType がどちらの場合も ArrayList.class を返すため、以下のクライアントのシリアル化がクラス キャスト例外で失敗することです。

    List<Clients> clients;
    // code to get clients from database. 
    String jsonString = mapper.writeValueAsString(clients);

質問は、どのシリアライザーを使用するかをジャクソンに伝える方法ですか?

resteasyでjsonシリアライザーとしてjacksonを使用しています。

-- @ HiJon89 に応じて編集 「リスト」を返すビジネス オブジェクトと、リストを返す別のビジネス オブジェクトがあります。私が必要とする方法は、Busines オブジェクトが「リスト」を返すときに、リスト全体に ProductsListSerializer を使用する必要があることです。Business Object が「List」を返す場合、CustomClientsSerializer を List 全体に使用する必要があります。私のユースケースでは、シリアル化された json に追加の要素を追加します 'eg:__count, __metadata , __references ' Collection ごとに __count は 1 つだけです。Contentusing プロパティでのみ使用できます。助言がありますか ?

4

2 に答える 2

3

コレクション内にある場合、このタイプのシリアル化/逆シリアル化を実際に異なる方法で処理する必要がありますか?Productそうでない場合は、次のようなものでクラスに注釈を付けることができ@JsonSerialize(using = ProductSerializer.class)ます。Jacksonは、Product(コレクション内を含む)に遭遇したときはいつでもシリアライザーを使用します。

コレクション内で実際に異なる処理が必要な場合は、クラスに次のような注釈を付けることができます@JsonSerialize(using = ProductSerializer.class, contentUsing = ProductInCollectionSerializer.class)。これは上記と同じことを行いますが、ProductInCollectionSerializerJacksonが。を含むコレクションに遭遇したときに代わりにシリアル化に使用される点が異なりProductます。

コメントに基づいて編集:

JacksonはコレクションをJSON配列としてシリアル化するため、これらの追加のプロパティを配置する場所はありません。JacksonがJSON配列といくつかの追加のメタデータを含むJSONオブジェクトを返すようにしたいようです。この場合、最善のアプローチは、List<Product>次のようなオブジェクトでラップすることです。

public class ProductListWrapper {
    private final List<Product> products;

    public ProductListWrapper(List<Product> products) {
        this.products = products;
    }

    public List<Product> getProducts() {
        return products;
    }

    @JsonProperty("_count")
    public int getCount() {
        return getProducts() == null ? 0 : getProducts().size();
    }
}

その後、Jacksonは、カスタムシリアライザーを作成しなくてもこのオブジェクトをシリアル化でき、次のようなJSONを生成します。

{
    "products": [....]
    "_count": 25
}
于 2013-01-22T11:32:27.903 に答える
0

simplemodule を拡張するか、com.fasterxml.jackson.databind.Module を拡張することで可能です。私は2番目のアプローチを取りました。以下、変更点まとめ

JavaType をパラメーターとして受け取るメソッドを追加しました。

    public <T> TypedModule addSerializer(JavaType type, JsonSerializer<T> ser)
{
    if (_serializers == null) {
        _serializers = new TypedSerializers();
    }
    _serializers.addSerializer(type, ser);
    return this;
}

上記のメソッドは、新しいセリライザーをに追加します

protected TypedSerializers _serializers = null;

クラス「TypedSerializers extends Serializers.Base」は、型指定されたすべてのシリアライザーを HashMap に格納します。

TypedSerializers の findSerializer メソッドのロジックを変更しました

public JsonSerializer<?> findSerializer(SerializationConfig config,
        JavaType type, BeanDescription beanDesc) {

    Class<?> cls = type.getRawClass();
    ClassKey key = new ClassKey(cls);
    JsonSerializer<?> ser = null;
    if (_javaTypeMappings != null) {
        ser = _javaTypeMappings.get(type.toString());
        if (ser != null) {
            return ser;
        }
    }
 ..... process normal serilaizers ...

customserializer の登録時に以下の変更が必要です

    TypedModule simpleModule = new TypedModule("TypedModule", new Version(1, 0, 0, null));       
    JavaType productlist = this.getTypeFactory().constructCollectionType(List.class, Product.class);
    JavaType clientlist = this.getTypeFactory().constructCollectionType(List.class, Client.class);
    simpleModule.addSerializer(productlist,  new prodctlistserializer());
    simpleModule.addSerializer(clientlist, new clientlistserializer() );
    this.registerModule(simpleModule);

結果として生じる動作は、'List of type Product' が ObjectMapper に渡されると、適切なセリラライザーを見つけようとすることです。_javaTypeMappings のマップで汎用シリアライザーを維持しています。Objecmapper は findSerializer を実行します。findSerializer は、最初に _javaTypeMappings で使用可能なシリアライザーをチェックします。この場合、prodctlistserializer を返します。「タイプ Client のリスト」が渡されると、clientlistserializer が返されます。

com.fasterxml.jackson.databind.Module の下のすべてのソース コードをプロジェクトのパッケージに取り、上記の変更を追加しました。

于 2013-01-24T06:01:13.107 に答える