0

我如何告诉杰克逊为每个通用集合类型使用不同的序列化程序。我有一个 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序列化程序。

--编辑以响应@HiJon89 我有一个返回“列表”的业务对象和另一个返回列表的业务对象。我需要的方式是当 Busines 对象返回一个“列表”时,应该将 ProductsListSerializer 用于整个列表。并且当业务对象返回“列表”时,应将 CustomClientsSerializer 用于整个列表。在我的用例中,我将附加元素附加到序列化的 json 'eg:__count, __metadata, __references' 每个集合只有一个 __count。Contentusing 只能用于属性。有什么建议么 ?

4

2 回答 2

3

您是否真的希望这种类型的序列化/反序列化在集合内时以不同方式处理?如果没有,您可以使用以下内容注释Product类:@JsonSerialize(using = ProductSerializer.class)杰克逊将在遇到 a Product(包括集合内部)时使用您的序列化程序。

如果您在集合内部确实需要不同的处理,您可以使用以下内容对类进行注释:@JsonSerialize(using = ProductSerializer.class, contentUsing = ProductInCollectionSerializer.class). 这将做与上面相同的事情,除了ProductInCollectionSerializer当 Jackson 遇到包含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。我采取了第二种方法。以下是更改摘要

添加了将 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 ...

注册customerializer时需要进行以下更改

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

产生的行为是,当“产品类型列表”传递给 ObjectMapper 时,它会尝试找到合适的序列化器。我们在 _javaTypeMappings 的映射中维护通用序列化程序。Objecmapper 执行 findSerializer。findSerializer 首先检查 _javaTypeMappings 中的可用序列化程序。在这种情况下,它返回 prodctlistserializer。当传递“客户端类型列表”时,它返回客户端列​​表序列化器。

我已将 com.fasterxml.jackson.databind.Module 下的所有源代码放入我的项目中的一个包中,并添加了上述更改。

于 2013-01-24T06:01:13.107 回答