反序列化 jackson 中的 bson long primitive json
Deserialize bson long primitive json in jackson
我正在使用 MongoDB 作为我们的数据存储,但我们想将 Jackson 用于 serialization/deserialization(Mongo pojo 类 几乎无法处理杰克逊的许多场景 - 例如建筑商)。
我们使用自定义 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 中检索到一个长度大于 Integer.MAXVALUE 的文档。发生这种情况时,反序列化会失败并显示以下消息:
原因:com.fasterxml.jackson.databind.JsonMappingException:无法反序列化长出 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;
}
但是 BsonLongDeserializer 从未被 Jackson 调用(原语处理方式不同并且可能使已注册的反序列化器短路吗?)。
杰克逊版本 2.9.3。 Mongo数据库驱动程序版本 3.6。
如果有人对攻击这个问题的角度有任何建议,我将不胜感激。
似乎没有帮助的参考文章:
我通过创建一个 JsonWriterSettings 对象来抑制奇怪的 json 反序列化,从而修复了 Mongo 方面的问题,从而使其正常工作。这来自这里:converting Document objects in MongoDB 3 to POJOS
编解码器现在看起来像这样:
class JacksonCodec<T> implements Codec<T> {
private final ObjectMapper objectMapper;
private final Codec<BsonDocument> rawBsonDocumentCodec;
private final Class<T> type;
public JacksonCodec(ObjectMapper objectMapper,
CodecRegistry codecRegistry,
Class<T> type) {
this.objectMapper = objectMapper;
this.rawBsonDocumentCodec = codecRegistry.get(BsonDocument.class);
this.type = type;
}
@Override
public T decode(BsonReader reader, DecoderContext decoderContext) {
try {
//
JsonWriterSettings settings = JsonWriterSettings.builder().int64Converter((value, writer) -> writer.writeNumber(value.toString())).build();
BsonDocument document = rawBsonDocumentCodec.decode(reader, decoderContext);
String json = document.toJson(settings);
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;
}
}
我正在使用 MongoDB 作为我们的数据存储,但我们想将 Jackson 用于 serialization/deserialization(Mongo pojo 类 几乎无法处理杰克逊的许多场景 - 例如建筑商)。
我们使用自定义 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 中检索到一个长度大于 Integer.MAXVALUE 的文档。发生这种情况时,反序列化会失败并显示以下消息:
原因:com.fasterxml.jackson.databind.JsonMappingException:无法反序列化长出 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;
}
但是 BsonLongDeserializer 从未被 Jackson 调用(原语处理方式不同并且可能使已注册的反序列化器短路吗?)。
杰克逊版本 2.9.3。 Mongo数据库驱动程序版本 3.6。
如果有人对攻击这个问题的角度有任何建议,我将不胜感激。
似乎没有帮助的参考文章:
我通过创建一个 JsonWriterSettings 对象来抑制奇怪的 json 反序列化,从而修复了 Mongo 方面的问题,从而使其正常工作。这来自这里:converting Document objects in MongoDB 3 to POJOS
编解码器现在看起来像这样:
class JacksonCodec<T> implements Codec<T> {
private final ObjectMapper objectMapper;
private final Codec<BsonDocument> rawBsonDocumentCodec;
private final Class<T> type;
public JacksonCodec(ObjectMapper objectMapper,
CodecRegistry codecRegistry,
Class<T> type) {
this.objectMapper = objectMapper;
this.rawBsonDocumentCodec = codecRegistry.get(BsonDocument.class);
this.type = type;
}
@Override
public T decode(BsonReader reader, DecoderContext decoderContext) {
try {
//
JsonWriterSettings settings = JsonWriterSettings.builder().int64Converter((value, writer) -> writer.writeNumber(value.toString())).build();
BsonDocument document = rawBsonDocumentCodec.decode(reader, decoderContext);
String json = document.toJson(settings);
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;
}
}