2

How can I declare a map variable using Generics, that has Class of X as Key, and the related Serializer of X as Value.

as example I want to have a Map that can contains:

K, V
BigDecimal.class, new BigDecimalSerializer()
LocalDate.class, new LocalDateSerializer()
Date.class, new DateSerializer()

Serializer example:

public class BigDecimalSerializer extends JsonSerializer<BigDecimal> {

    @Override
    public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeString(FormatUtils.format(value));
    }

}

I tried Map<Class<?>, ? extends JsonSerializer<?>>

@Getter
@AllArgsConstructor
public class CsvWriterConfig {
    
    private final Map<Class<?>, ? extends JsonSerializer<?>> serializers;
    private final char separator;
    
}

but adding them to SimpleModule

SimpleModule module = new SimpleModule();
serializers.forEach(module::addSerializer);

gives me an error:

The type SimpleModule does not define addSerializer(Class<capture#5-of ?>, capture#4-of ? extends JsonSerializer<?>) that is applicable here

The SimpleModule addSerializer is:

public <T> SimpleModule addSerializer(Class<? extends T> type, JsonSerializer<T> ser)
{
    _checkNotNull(type, "type to register serializer for");
    _checkNotNull(ser, "serializer");
    if (_serializers == null) {
        _serializers = new SimpleSerializers();
    }
    _serializers.addSerializer(type, ser);
    return this;
}

1 Answer 1

2

Currently, there's no good solution for it .

one possible approach is to use raw types (and delete generics whatsoever)

another would be to add a method to add serializers to the module, and cast types within the method:

    @SuppressWarnings("unchecked")
    private <T> void addSerializers(SimpleModule module) {
        this.serializers.forEach((type, serializer) ->
                module.addSerializer((Class<? extends T>) type, (JsonSerializer<T>) serializer));
    }

btw, the code above is taken from spring-web sources

The third approach would be to create a wrapper for a Map with accessors methods, which will ensure that no incorrect type-serializer pairs were added. e.g.:

        SerializersWrapper serializersWrapper = new SerializersWrapper();
        SimpleModule module = new SimpleModule();
        serializersWrapper.getAll().forEach(module::addSerializer);

and the wrapper code is


import com.fasterxml.jackson.databind.JsonSerializer;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class SerializersWrapper {
    private final Map<Class,JsonSerializer> serializers = new HashMap<>();

    public <T> void addSerializer(Class<T> type, JsonSerializer<T> serializer) {
        serializers.put(type, serializer);
    }

    public <T> JsonSerializer<T>  getSerializer(Class<T> type){
        return serializers.get(type);
    }

    public <T> Map<Class<T>,JsonSerializer<T>> getAll(){
        return (Map<Class<T>, JsonSerializer<T>>) (Map) Collections.unmodifiableMap(serializers);
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.