我刚刚开始使用 play 框架、jongo 和 MongoDB 开发一个项目。 该项目最初是在 Play 2.1 中使用 pojo 编写的,其 String id 字段同时注释有: @Id 和 @ObjectId 这将作为 ObjectId 持久保存到 Mongo,并且反序列化时会将 id 输出为: "id":"53fcb9ede4b0b18314098d10" 例如。
自从升级到 Jongo 1.1 和 Play 2.3.3 后,id 属性在反序列化时始终命名为“_id”,我希望该属性保留字段名称,但我无法使用 @JsonProperty("custom_name") 作为 Jongo @Id注释在幕后执行 @JsonProperty("_id") 。
import org.jongo.marshall.jackson.oid.Id;
import org.jongo.marshall.jackson.oid.ObjectId;
public class PretendPojo {
@Id
@ObjectId
private String id;
private String name;
public PretendPojo() {
}
public PretendPojo(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
如果我通过 RoboMongo 查看 POJO,它们在 MongoDB 中持久化时看起来像这样
{
"_id" : ObjectId("53fc984de4b0c34f1905b8ee"),
"name" : "Owen"
}
但是,当我反序列化它们时,如果保留两个注释,我会得到以下 json:
{"name":"Owen","_id":{"time":1409072858000,"date":1409072858000,"timestamp":1409072858,"new":false,"timeSecond":1409072858,"inc":308487737,"machine":-458223042}}
如果我只使用 @Id 注释,则会得到以下输出。
{"name":"Owen","_id":"53fcbedae4b0123e12632639"}
我有一个使用上面的 PretendPojo 表演的测试用例:
@Test
public void testJongoIdDeserialization() throws UnknownHostException {
DB database = new MongoClient("localhost", 27017).getDB("jongo");
Jongo jongo = new Jongo(database);
MongoCollection collection = jongo.getCollection("jongo");
collection.save(new PretendPojo("Owen"));
PretendPojo pretendPojo = collection.findOne("{name: \"Owen\"}").as(PretendPojo.class);
JsonNode json = Json.toJson(pretendPojo);
assertNotNull(json.get("id"));
}
当尝试使用自定义反序列化器时,我永远无法获取对象 ID,我似乎只能访问当前正在反序列化的日期/时间/时间戳数据。
理想情况下,我正在寻找的输出是:
{"name":"Owen","id":"53fcbedae4b0123e12632639"}
任何帮助将不胜感激! :)
ObjectIdSerializer 始终将使用 @ObjectId 映射的属性写入 ObjectId 的新实例。当您将此属性映射到字符串时,这是错误的。
为了避免这种行为,我编写了一个 NoObjectIdSerializer :
public class NoObjectIdSerializer extends JsonSerializer<String> {
@Override
public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeString(value);
}
}
像这样使用:
@ObjectId
@JsonSerialize(using = NoObjectIdSerializer.class)
protected final String _id;
有一个未解决的问题。
我认为 Jackson 中有一个注释可以让您更改属性名称,我认为是:@JsonProperty,但您可以在此链接中看到所有可能的注释:
https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations
我希望这能解决您的问题
您可以尝试使用@JsonValue,Jongo似乎不使用它们,但如果没有开发人员的任何回应,这种行为可能会在未来的版本中发生变化。
@JsonValue
public Map<String, Object> getJson() {
Map<String, Object> map = new HashMap<>();
map.put("name", name);
map.put("id", id);
return map;
}
更合适的解决方案是尝试将
@JsonView
与 @Id
注释结合起来@Id
@JsonView(Views.DatabaseView.class)
private String id;
@JsonView(Views.PublicView.class)
public String getId() {
return id;
}
Jongo 的行为自 1.1 以来已发生变化,以便更一致地处理其自己的注释。
如果你的'_id'是一个字符串,并且你希望这个字段作为字符串存储到Mongo中,那么只需要@Id。
String 属性上的@Id + @ObjectId 意味着:
“名为“foo”的字符串属性是一个有效的 ObjectId。该属性必须使用名称“_id”存储,并且必须作为 ObjectId 进行处理。”
从 Jackson 2.13.1 及更高版本开始,可以使用 @JsonAlias 注释,该注释可在反序列化期间用于填充对象中在 JSON 中具有不同名称的字段。 'id' 属性可以使用此注释 @JsonAlias("_id") 进行注释,以将 _id 从 MongoDB 读取到 'id'