データストアとしてMongoDBを使用していますが、ジャクソンをシリアライゼーション/デシリアライズに使用したいと考えています(例えば、Mongo pojoクラスではJacksonのビルダーほどのシナリオは扱えません)。ジャーソンのbson longプリミティブjsonをデシリアライズする
私たちは、カスタム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;
}
}
我々はInteger.MAXVALUEよりも大きい、長いを持っているモンゴからドキュメントを取得するまで、これは、正常に動作します。その場合、次のメッセージでデシリアライズが失敗します。
原因:com.fasterxml.jackson.databind.JsonMappingException:START_OBJECTトークンからlongのインスタンスを逆シリアル化できません。 BSONを見ると
は、ここではモンゴデータは私達に戻って来ている方法は次のとおりです。
"日付スタンプ":{ "$ numberLong": "1514334498165"}
ので...私は考えていますジャクソンがこのケースを処理するために追加のデシリアライザを登録する必要があります(ID_START_OBJECTのトークンタイプをチェックし、存在する場合は解析し、そうでない場合は組み込みデシリアライザに委譲します)。
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;
}
}
し、それを登録します:私はObjectMapper SimpleModuleたシンプルなロングデシリアライザを登録しようとした
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はジャクソン(によって呼び出されることは決してありませんが別の方法で処理プリミティブと短絡登録デシリアライザです多分?)。
ジャクソン版2.9.3。 MongoDBドライババージョン3.6。
誰かがこれを攻撃するアングルについての提案があれば、私はそれを聞いていただければ幸いです。助けていないように見えます
参考記事:MongoDB "NumberLong/$numberLong" issue while converting back to Java Object