有至少两种可能的方法来实现这个。可能最正确的方法是使用GSON TypeAdapter 来配置如何将ObjectId写入(和读取)JSON。你需要创建一个实现TypeAdapter
的东西,并将其注册到GsonBuilder
中,这样GSON就知道有一种特殊的方法来处理ObjectIds。
我编写了一个小测试来证明这个方法可以工作,使用您的用例和示例对象(但出于简洁起见省略了revNo
字段):
@Test
public void shouldWriteCorrectJSON() {
TaskObject taskObject = new TaskObject();
taskObject._id = new ObjectId("51eae100c2e6b6c222ec3431");
Gson gson = new GsonBuilder().registerTypeAdapter(ObjectId.class, new ObjectIdTypeAdapter()).create();
String gsonString = gson.toJson(taskObject);
assertThat(gsonString, is("{\"_id\":{\"$oid\":\"51eae100c2e6b6c222ec3431\"}}"));
}
private class ObjectIdTypeAdapter extends TypeAdapter<ObjectId> {
@Override
public void write(final JsonWriter out, final ObjectId value) throws IOException {
out.beginObject()
.name("$oid")
.value(value.toString())
.endObject();
}
@Override
public ObjectId read(final JsonReader in) throws IOException {
in.beginObject();
assert "$oid".equals(in.nextName());
String objectId = in.nextString();
in.endObject();
return new ObjectId(objectId);
}
}
请注意,该测试断言JSON的格式应该是您期望的样子,并且我必须创建一个ObjectIdTypeAdapter
,它知道ObjectId字段的名称为"$oid",值仅为ObjectID的字符串值,并且不会单独序列化所有字段。
还要注意,如果您更改对象写入JSON的方式,您也需要更改读取的方式。因此,我还实现了read
来检查字段名称是否正确(如果不正确,您应该在这里抛出异常而不是使用简单的assert),然后读取该值并从该字符串值创建ObjectId。
在实际情况中,您可能还需要检查这两种情况下的null值。
���为我是一个负责任的编码人员,所以我还编写了一个测试来展示读取情况也可以正常工作:
@Test
public void shouldReadFromJSON() {
Gson gson = new GsonBuilder().registerTypeAdapter(ObjectId.class, new ObjectIdTypeAdapter()).create();
TaskObject actualTaskObject = gson.fromJson("{\"_id\":{\"$oid\":\"51eae100c2e6b6c222ec3431\"}}", TaskObject.class);
TaskObject taskObject = new TaskObject();
taskObject._id = new ObjectId("51eae100c2e6b6c222ec3431");
assertThat(actualTaskObject._id, is(taskObject._id));
}
更多阅读: