Java 来自MongoDB BSON的Jackson ObjectMapper

Java 来自MongoDB BSON的Jackson ObjectMapper,java,json,mongodb,jackson,bson,Java,Json,Mongodb,Jackson,Bson,我得到了一个JSON,我将其序列化为MongoDBBasicDBObject,并将其插入数据库: String serialized = ""; try { serialized = OBJECT_MAPPER.writeValueAsString(customEx.getOut().getBody()); } catch (JsonProcessingException e) { e.printStackTrace(); }

我得到了一个JSON,我将其序列化为MongoDB
BasicDBObject
,并将其插入数据库:

    String serialized = "";
    try {
        serialized = OBJECT_MAPPER.writeValueAsString(customEx.getOut().getBody());
    } catch (JsonProcessingException e) {
        e.printStackTrace();
    }

    collection.update(upsertQuery, BasicDBObject.parse(serialized), true, false);
在从数据库读取
DBObject
时,我想使用
ObjectMappers'
readValue()
和给定的类将其转换为POJO:

    public static <T> T fromDB(DBObject o, Class<T> clazz) {
    try {
        return OBJECT_MAPPER.readValue(o.toString(), clazz);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}
但是,这对于较旧的JavaMongoDB版本来说效果很好。现在,长值序列化为BSON,如下所示:

"date": {
    "$numberLong": "1551172199214"
}
public static <T> T fromDB(DBObject o, Class<T> clazz) {
    try {
        BsonDocument parse = BsonDocument.parse(o.toString());
        return OBJECT_MAPPER.readValue(parse.toJson(), clazz);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}
当我尝试使用jacksons
ObjectMapper对其进行反序列化时,我得到

无法反序列化
javax.xml.datatype.XMLGregorianCalendar
超出起始\u对象标记的实例

原因对我来说很清楚,因为long值位于自己的BSON-
样式
对象中

到目前为止,我已经尝试过像这样使用
BsonDocument

"date": {
    "$numberLong": "1551172199214"
}
public static <T> T fromDB(DBObject o, Class<T> clazz) {
    try {
        BsonDocument parse = BsonDocument.parse(o.toString());
        return OBJECT_MAPPER.readValue(parse.toJson(), clazz);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}
公共静态T fromDB(dbo对象,类clazz){
试一试{
BsonDocument parse=BsonDocument.parse(o.toString());
返回OBJECT_MAPPER.readValue(parse.toJson(),clazz);
}捕获(IOE异常){
e、 printStackTrace();
}
返回null;
}
但这仍然无法将BSON部分转换为JSON

有没有办法使用Jacksons
ObjectMapper将BSON反序列化到给定的类?

或者只需将其转换为
DBObject
,而不使用BSON部件?

看起来您需要配置
ObjectMapper
以不同的方式反序列化
xmlgoriiancalendar

public class XMLGregorianCalendarDeserializer extends JsonDeserializer<XMLGregorianCalendar> {
private ObjectMapper objectMapper = new ObjectMapper();

@Override
public XMLGregorianCalendar deserialize(
    JsonParser jsonParser, DeserializationContext deserializationContext)
    throws IOException, JsonProcessingException {
  Map<String, String> bsonStringAsMap =
      objectMapper.readValue(
          jsonParser.readValueAsTree().toString(), new TypeReference<Map<String, String>>() {});

  String timestampString = bsonStringAsMap.get("$numberLong");
  if (timestampString != null && !timestampString.isEmpty()) {
    long timestamp = Long.parseLong(timestampString);
    Date date = new Date(timestamp);
    GregorianCalendar gregorianCalendar = new GregorianCalendar();
    gregorianCalendar.setTime(date);
    return DatatypeFactory.newInstance().newXMLGregorianCalendar(gregorianCalendar);
  }
  return null;
  }
}

如果日历字段已包装,则需要将其展开。我们可以扩展已经实现的
CoreXmlDeserializer。GregorianCalendarDeserializer

class XmlGregorianCalendarDeserializer extends CoreXMLDeserializers.GregorianCalendarDeserializer {

    @Override
    public XMLGregorianCalendar deserialize(JsonParser jp, DeserializationContext ctxt)
        throws IOException {
        jp.nextToken(); // Skip FIELD_NAME
        jp.nextToken(); // Skip VALUE_STRING

        XMLGregorianCalendar calendar = super.deserialize(jp, ctxt);

        jp.nextToken(); // Skip END_OBJECT

        return calendar;
    }
}
如果总是包装
XMLGregorianCalendar
,我们可以使用
SimpleModule
注册此反序列化程序。请参见以下示例:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ext.CoreXMLDeserializers;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.io.IOException;
import javax.xml.datatype.XMLGregorianCalendar;

public class Test {

    public static void main(String[] args) throws Exception {
        SimpleModule wrappedCalendarModule = new SimpleModule();
        wrappedCalendarModule.addDeserializer(XMLGregorianCalendar.class, new XmlGregorianCalendarDeserializer());

        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(wrappedCalendarModule);
        String json = "{\n"
            + "   \"date\":{\n"
            + "      \"$numberLong\":\"1551172199214\"\n"
            + "   },\n"
            + "   \"name\":\"Rick\"\n"
            + "}";
        System.out.println(mapper.readValue(json, Wrapper.class));
    }
}

class Wrapper {

    private XMLGregorianCalendar date;
    private String name;

    // getters, setters, toString
}
以上代码打印:

Wrapper{date=2019-02-26T09:09:59.214Z, name='Rick'}

尝试使用MongoJack将来自MongoDB的Json(Bson)映射到您的ObjectsSample:ObjectMapper myObjectMapper=。。。配置(myObjectMapper);JacksonDBCollection coll=JacksonDBCollection.wrap(DBCollection DBCollection、BlogPost.class、String.class、myObjectMapper);更多详情: