2013-11-01 93 views
1

在內部,我使用地圖快速查找值,例如, private Map<String, CustomObject> lookupTable,其中CustomObject有一些id字段被用作lookupTable中的密鑰。序列化映射的鍵是很愚蠢的,所以我想註釋內部變量來只序列化值。這不起作用,很明顯:Jackson將地圖序列化爲列表

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