如何将从mongoDB获取的json文档反序列化为POJO?...(从Morphia迁移到Java Mongo Driver 3.0)

时间:2015-08-20 09:50:09

标签: java json mongodb mongodb-java morphia

背景

最初,Morphia被用来与mongo数据库进行交互。这很好,工作得很好,但有一个警告......一些映射异常正在溢出并堵塞日志。 See my Unresolved Question on that particular issue。 < ===这并没有阻止应用程序正常运行。 Morphia帮助将文档映射到相应的实体(基本上是POJO ),并且这些文档很容易呈现给视图。

然而,经过深思熟虑并因为异常问题没有得到解决,并且由于MongoDB Java Driver 3.0的新功能,我决定从Morphia迁移到MongoDB-Java-Driver3.0(MJD3) 0.0)

<小时/> 在检查文件(以前由morphia存储)时,我可以看到:

"_id" : ObjectId("55706df5e4b00146ea69622b"),
"className" : "packageName.NewsCategory",
"categoryName" : "Maritime",
"uid" : NumberLong(11),
"createdAt" : ISODate("2015-06-04T15:25:41.096Z"),
"updatedAt" : ISODate("2015-06-04T15:25:41.096Z"),
"active" : true

此外,模型 NewsCategory 看起来像这样;

public class NewsCategory{
    private ObjectId id;
    private String categoryName;
    private Long uid;
    private Date createdAt;
    private Date updatedAt;
    private boolean active;

    //getters...
    //setters...
}

<小时/> 我的策略

因为我以前使用的是Morphia,所以模型(作为POJO)作为属性传递给视图 (。vm - velocity templates) ,其中正在读取值来自以下字段: $!newsCategory.id $!newsCategory.categoryName $!newsCategory.createdAt ,例如

<a href="/news/categories/$!newsCategory.id"> Edit </a>

现在,因为 我不想修改Servelet和/或View Layer ,我确保在业务层中json字符串获取使用gson;

反序列化到相应的模型中

NewsCategory newsCategory = new GsonBuilder().create().fromJson(json, NewsCategory.class);

<小时/> 挑战 - 1

使用document类型为org.bson.Document并使用MongoDB-Java-Driver3.0(MJD3.0),可以从MongoDB中正确检索 NewsCategory 文档,没问题,当我打电话

String json = document.toJson(); ...这里是json结构的样子;

{
    "_id": {
        "$oid": "54ad4568e451500a45f60200"
    },
    "className": "packageName.NewsCategory",
    "categoryName": "General",
    "uid": {
        "$numberLong": "1"
    },
    "createdAt": {
        "$date": 1420641640457
    },
    "updatedAt": {
        "$date": 1429285029337
    },
    "active": true
}

<小时/> 问题

使用我之前描述的策略,从json派生的document.toJson()结构无法轻松反序列化到相应的 NewsCategory 模型,这要归功于格式。

<小时/> 挑战 - 2

我使用document直接将gson转换为json,如下所示;

String json = new GsonBuilder().create().toJson(document); ...这里是json结构的样子;

{
    "_id": {
        "timestamp": 1420641640,
        "machineIdentifier": 14963024,
        "processIdentifier": 2629,
        "counter": 16122368
    },
    "className": "packageName.NewsCategory",
    "categoryName": "General",
    "uid": 1,
    "createdAt": "Jan 7, 2015 3:40:40 PM",
    "updatedAt": "Apr 17, 2015 4:37:09 PM",
    "active": true
}

这是更理想的方式,我可以使用我通常的策略获取 NewsCategory 对象;

NewsCategory newsCategory = new GsonBuilder().create().fromJson(json, NewsCategory.class);

<小时/> 他们的另一个问题

_id字段已被分解为ObjectId个组件,因此无法将ID检索为newsCategory.id甚至newsCategory._id

然而,虽然我以前使用的是morphia,但只需使用newsCategory.id

就可以检索到它。

<小时/> 主要问题

将这些json字符串反序列化为相应的 NewsCategory 模型的适当方法是什么,同时仍然确保使用常规点在视图中仍然可以正常访问所有必需的字段(。 )注释( 尤其是id字段 )?

CHALLENGES 1&amp;上述2 将受到高度赞赏。

谢谢!

编辑:

我已尝试过@ cichystefan的方法,挑战仍然是如何获取_id字段的价值

newsCategory现在属于org.bson.Document类型,原因很明显,$!newsCategory.id显然是空的或null,因为当我检查定义为{{的视图中的html部分时1}}在谷歌浏览器这里是我看到的... <a href="/news/categories/$!newsCategory.id"> ...

现在,本能说通过执行<a href="/news/categories/">来获取_id部分,但这只是将整个文档作为字符串溢出并将$!newsCategory._id部分附加到字符串的末尾。

._id

3 个答案:

答案 0 :(得分:0)

你为什么要对JSON做任何事情? 难道你不能简单地使用检索到的Document对象(驱动程序已经解析了JSON来为你准备该对象)并将其映射到代码中的POJO吗?

(谁知道,也许在很多情况下可能根本不需要转换,因为Document实现了Map,你在POJO和Document中的名字相互匹配,因此应该通过模板引擎很好地对待它。不复杂......)

答案 1 :(得分:0)

我发现自己用GSON将文档反序列化到POJO将不会对_id工作而不做一些修改。导致POJO中的_id与MongoDB中存储的原始_id不同。

看看这个解决方案来解决它。 Converting BSON Type ObjectId to JSON (Storing in Mongodb) -Java

答案 2 :(得分:0)

如何遍历文档的JSON并替换所有&#34; _id:{&#34; $ oid&#34; :&#34; ......&#34;与id?

ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(bsonFile);
replaceIds(jsonNode);

void replaceIds(JsonNode rootNode) {
    if (rootNode.has("_id")) {
        String id = rootNode.get("_id").get("$oid").asText();
        ObjectNode objectNode = (ObjectNode) rootNode;
        objectNode.remove("_id");
        objectNode.put("id", id);
     }
    for (JsonNode childeNode : rootNode) {
        replaceIds(childeNode);
    }
}

这会使所有_id部分变平。 当然,如果您的POJO字段并非都具有&#34; id&#34;名称,您还需要遍历您的对象并找到相应的名称 - 它不应该太难!毕竟,你只是在寻找ObjectId并且可以假设订单是相同的,只要你的存储库中没有旧对象,那时字段的排序方式就不同了。