2013-11-01 2 views
1

Внутренне я использую карту для быстрого поиска значений, например. private Map<String, CustomObject> lookupTable, где CustomObject имеет поле id, которое используется в качестве ключа в lookupTable. Глупо сериализовывать ключи карты, поэтому я хочу аннотировать внутреннюю переменную, чтобы сериализовать только значения. Это не работает, очевидно:Jackson Serialize Map to List

@JsonSerialize(as = List.class) 
private final Map<String, CustomObject> lookupTable; 

Почему обычай сериализатору не будет работать

Я создал пользовательский сериалайзер как:

public static class MapValuesJsonSerializer extends JsonSerializer<Map<?, ?>> { 

    @Override 
    public void serialize(
     Map<?, ?> value, 
     JsonGenerator generator, 
     SerializerProvider provider) 
     throws IOException, JsonProcessingException { 

     generator.writeObject(value.values()); 
    } 
} 

Затем я аннотированный поле соответственно:

@JsonSerialize(using = MapValuesJsonSerializer.class) 
public Map<String, CustomObject> lookupTable; 

Это работает с некоторым тестовым кодом Java, но он ломается при использовании драйвера MongoDB и MongoJack. Я получаю некоторое бесполезное исключение, которое я считаю, это потому, что он на самом деле не Сериализация возвращаемого объекта и, вместо этого, просто пытаюсь передать, что необработанный объект в BSON сериализатор:

Caused by: java.lang.IllegalArgumentException: can't serialize class CustomObject 
    at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:270) 
    at org.bson.BasicBSONEncoder.putIterable(BasicBSONEncoder.java:295) 
    at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:234) 
    at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:174) 
    at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:120) 
    at com.mongodb.DefaultDBEncoder.writeObject(DefaultDBEncoder.java:27) 
    at com.mongodb.OutMessage.putObject(OutMessage.java:289) 
    at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:239) 
    at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:204) 
    at com.mongodb.DBCollection.insert(DBCollection.java:148) 
    at com.mongodb.DBCollection.insert(DBCollection.java:91) 
    at org.mongojack.JacksonDBCollection.insert(JacksonDBCollection.java:255) 
    // My code (not the serializer)... 

ответ

2

Конечно, как только я спросите, я выясню решение.

Используя сериализатор выше, используйте provider, чтобы сериализовать значения вместо generator. Вот код:

/** 
* <p> 
* Serializes the values of some map into a list. 
* <p> 
* 
* @author John Jenkins 
*/ 
public class MapValuesJsonSerializer extends JsonSerializer<Map<?, ?>> { 
    /* 
    * (non-Javadoc) 
    * @see com.fasterxml.jackson.databind.JsonSerializer#serialize(java.lang.Object, com.fasterxml.jackson.core.JsonGenerator, com.fasterxml.jackson.databind.SerializerProvider) 
    */ 
    @Override 
    public void serialize(
     final Map<?, ?> value, 
     final JsonGenerator generator, 
     final SerializerProvider provider) 
     throws IOException, JsonProcessingException { 

     provider.defaultSerializeValue(value.values(), generator); 
    } 
} 
Смежные вопросы