这些答案都没有达到我想要的效果。我遇到了麻烦,因为当我将JSON字符串序列化到MongoDB时,它被存储为字符串。虽然是格式良好的字符串,但仍然是一个字符串。
我使用com.fasterxml.jackson.databind.ObjectMapper将我的对象转换为/从JSON,并且我希望继续使用这个类。我有以下方法:
public enum JsonIntent {NONE, MONGODB};
public static ObjectMapper getMapper(final JsonIntent intent) {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.registerModule(new JodaModule());
if (intent == JsonIntent.MONGODB) {
SimpleModule testModule = new SimpleModule("MyModule", new Version(1, 0, 0, null, null, null));
testModule.addSerializer(Date.class, new StdSerializer<Date>(Date.class) {
private static final long serialVersionUID = 1L;
@Override
public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
try {
if (value == null) {
jgen.writeNull();
} else {
jgen.writeStartObject();
jgen.writeFieldName("$date");
String isoDate = ISODateTimeFormat.dateTime().print(new DateTime(value));
jgen.writeString(isoDate);
jgen.writeEndObject();
}
} catch (Exception ex) {
Logger.getLogger(JsonUtil.class.getName()).log(Level.SEVERE, "Couldn't format timestamp " + value + ", writing 'null'", ex);
jgen.writeNull();
}
}
});
testModule.addDeserializer(Date.class, new StdDeserializer<Date>(Date.class) {
private static final long serialVersionUID = 1L;
@Override
public Date deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException {
JsonNode tree = jp.readValueAsTree();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
try {
return ISODateTimeFormat.dateTime().parseDateTime(tree.get("$date").textValue()).toDate();
} catch (Throwable t) {
throw new IOException(t.getMessage(), t);
}
}
});
mapper.registerModule(testModule);
}
return mapper;
}
现在,我可以运行以下测试代码:
BObjectMapper mapper = getMapper(JsonUtil.JsonIntent.NONE);
Date d1 = new Date();
String v = mapper.writeValueAsString(d1);
System.out.println("Joda Mapping: " + v);
Date d2 = mapper.readValue(v, Date.class);
System.out.println("Decoded Joda: " + d2);
mapper = getMapper(JsonUtil.JsonIntent.MONGODB);
v = mapper.writeValueAsString(d1);
System.out.println("Mongo Mapping: " + v);
d2 = mapper.readValue(v, Date.class);
System.out.println("Decoded Mongo: " + d2);
输出如下:
Joda Mapping: "2016-06-13T14:58:11.937+0000"
Decoded Joda: Mon Jun 13 10:58:11 EDT 2016
Mongo Mapping: {"$date":"2016-06-13T10:58:11.937-04:00"}
Decoded Mongo: Mon Jun 13 10:58:11 EDT 2016
请注意,将发送到MONGODB的JSON定义了一个包含名为“$date”的字段的值。这告诉MongoDB这是一个日期对象。当我查看Mongo时,我看到以下内容:
"importDate" : ISODate("2016-05-18T18:55:07Z")
现在,我可以将该字段作为日期而不是字符串进行访问。
要将编码的JSON字符串添加到Mongo中,我的代码如下:
MongoDatabase db = getDatabase();
Document d = Document.parse(json);
db.getCollection(bucket).insertOne(d);
在这种情况下,“json”是编码的JSON字符串。因为它来自JSON字符串,它无法知道类型,除非它推断出这一点,这就是为什么我们需要“$date”部分的原因。 “bucket”只是一个字符串,表示要使用哪个表格。
顺便说一下,我发现如果我从Mongo中提取一个BSON对象并通过调用doc.toJson()(其中doc的类型为org.bison.Document,由查询返回)将其转换为JSON字符串,则日期对象将以长整型值而不是格式化的文本字符串存储。我没有检查过是否可以在以这种方式格式化后将数据推入mongo,但是,您可以修改上面显示的反序列化器来支持此操作,如下所示:
testModule.addDeserializer(Date.class, new StdDeserializer<Date>(Date.class) {
private static final long serialVersionUID = 1L;
@Override
public Date deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException {
JsonNode tree = jp.readValueAsTree();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
try {
JsonNode dateNode = tree.get("$date");
if (dateNode != null) {
String textValue = dateNode.textValue();
if (!Util.IsNullOrEmpty(textValue)) {
return ISODateTimeFormat.dateTime().parseDateTime(textValue).toDate();
}
return Util.MillisToDate(dateNode.asLong());
}
return null;
} catch (Throwable t) {
Util.LogIt("Exception: " + t.getMessage());
throw new IOException(t.getMessage(), t);
}
}
});
您可以按照以下方式将毫秒转换为日期或日期时间:
public static Date MillisToDate(final long milliseconds) {
if (milliseconds < 1) {
return null;
}
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(milliseconds);
return calendar.getTime();
}
public static DateTime MillisToDateTime(final long milliseconds) {
if (milliseconds < 1) {
return null;
}
return new DateTime(milliseconds);
}
ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JodaModule()); mapper.configure(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
输出如下 "createdTime":"2015-03-30T19:33:08.921Z"。我想要的格式类似于以下内容。 "createdTime":ISODate(“2015-01-20T16:39:42.132Z”)或者我错过了什么? - vishy@JsonSerialize
而不是@JsonSerializer
吗? - Naruto Sempai