2017-12-27 35 views
0

데이터 저장소로 MongoDB를 사용하고 있지만 직렬화/직렬화에 Jackson을 사용하고 있습니다. Mongo pojo 클래스는 Jackson과 거의 같은 시나리오를 처리하지 않습니다.jackson에서 bson long primitive json을 비 직렬화합니다.

우리는이 사용자 정의 CodecProvider를 사용하여 작업 한 - 여기 코덱 자체이다 : 우리가 Integer.MAXVALUE보다 크 긴있다 몽고에서 문서를 검색 할 때까지

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

이 잘 작동이. 이 경우 다음 메시지와 함께 비 직렬화가 실패합니다.

원인 : com.fasterxml.jackson.databind.JsonMappingException : START_OBJECT 토큰에서 긴 인스턴스를 deserialize 할 수 없습니다. bson 보면

, 여기에 몽고 데이터가 우리에게 돌아 오는 방법은 다음과 같습니다

"날짜 스탬프": { "$ NumberLong으로": "1514334498165"} 그래서

... 나는 생각하고 Jackson이이 케이스를 처리 할 수있는 추가 디시리얼라이저를 등록해야합니다 (토큰 유형 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

답변

0

나는 이상한 JSON의 직렬화를 억제하는 개체입니다 JsonWriterSettings를 생성하여 사물의 몽고 측을 고정하여 작업을 얻었다. 이것은 여기에서 온 :

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 { 
      //https://stackoverflow.com/questions/35209839/converting-document-objects-in-mongodb-3-to-pojos 
      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; 
    } 
} 
: converting Document objects in MongoDB 3 to POJOS

코덱은 이제 다음과 같습니다