【发布时间】:2018-06-07 16:22:15
【问题描述】:
我使用 MongoDB 作为我们的数据存储,但我们想使用 Jackson 进行序列化/反序列化(Mongo pojo 类处理的场景几乎没有 Jackson - 例如构建器)。
我们使用自定义 CodecProvider 进行这项工作 - 这是编解码器本身:
class JacksonCodec<T> implements Codec<T> {
private final ObjectMapper objectMapper;
private final Codec<RawBsonDocument> rawBsonDocumentCodec;
private final Class<T> type;
public JacksonCodec(ObjectMapper objectMapper,
CodecRegistry codecRegistry,
Class<T> type) {
this.objectMapper = objectMapper;
this.rawBsonDocumentCodec = codecRegistry.get(RawBsonDocument.class);
this.type = type;
}
@Override
public T decode(BsonReader reader, DecoderContext decoderContext) {
try {
RawBsonDocument document = rawBsonDocumentCodec.decode(reader, decoderContext);
String json = document.toJson();
return objectMapper.readValue(json, type);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
@Override
public void encode(BsonWriter writer, Object value, EncoderContext encoderContext) {
try {
String json = objectMapper.writeValueAsString(value);
rawBsonDocumentCodec.encode(writer, RawBsonDocument.parse(json), encoderContext);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
@Override
public Class<T> getEncoderClass() {
return this.type;
}
}
这工作正常,直到我们从 Mongo 检索一个 long 大于 Integer.MAXVALUE 的文档。发生这种情况时,反序列化失败并显示以下消息:
原因:com.fasterxml.jackson.databind.JsonMappingException:无法反序列化 long out of START_OBJECT 令牌的实例。
看看 bson,Mongo 数据是如何返回给我们的:
“dateStamp”:{“$numberLong”:“1514334498165”}
所以...我想我需要为 Jackson 注册一个额外的反序列化器来处理这种情况(检查 ID_START_OBJECT 的令牌类型,解析它是否存在,否则委托给内置的反序列化器)。我尝试使用 ObjectMapper SimpleModule 注册一个简单的 Long 反序列化器:
public class BsonLongDeserializer extends JsonDeserializer<Long>{
@Override
public Class<Long> handledType() {
return Long.class;
}
@Override
public Long deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
if (p.currentTokenId() != JsonTokenId.ID_START_OBJECT){
// have to figure out how to do this for real if we can get the deserilizer to actually get called
return ctxt.readValue(p, Long.class);
}
return null;
}
}
并注册:
private static ObjectMapper createMapper(){
SimpleModule module = new SimpleModule();
module.addDeserializer(Long.class, new BsonLongDeserializer());
ObjectMapper mapper = new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.registerModule(module);
return mapper;
}
但是 Jackson 永远不会调用 BsonLongDeserializer(原语的处理方式是否不同并且可能会使注册的反序列化器短路?)。
杰克逊版本 2.9.3。 MongoDB 驱动程序版本 3.6。
如果有人对攻击此问题的角度有任何建议,我将不胜感激。
似乎没有帮助的参考文章:MongoDB "NumberLong/$numberLong" issue while converting back to Java Object
【问题讨论】:
标签: java mongodb jackson jackson2