XPages:从大量文档创建JSON字符串

时间:2015-09-02 19:40:41

标签: java json dojo xpages

我一直在尝试创建一个带有大量文档的Json字符串,但是使用下面的代码但是我超出了范围或者必须等到5分钟b4字符串被大肆宣传如何优化代码?

public String getJson() throws NotesException {
    ...
    View view1 = ...;
    ViewNavigator nav =view1.createViewNav();
    ViewEntry ve = nav.getFirst();  
    JSONObject jsonMain = new JSONObject();     
    JSONArray items = new JSONArray();
    Document docRoot = null 
    while (ve != null) {
    docRoot= ve.getDocument();
        items.add(getJsonDocAndChildren(docRoot));
        ViewEntry veTemp = nav.getNextSibling(ve);
        ve.recycle();
        ve = docTemp;
    }
    jsonMain.put("identifier", "name");
    jsonMain.put("label", "name");
    jsonMain.put("items", items);
    return jsonMain.toJSONString();
}

private JSONObject getJsonDocAndChildren(Document doc) throws NotesException {

    String  name = doc.getItemValueString("Name");
    JSONObject jsonDoc = new JSONObject();
    jsonDoc.put("name", name);
    jsonDoc.put("field", doc.getItemValueString("field"));
    DocumentCollection responses = doc.getResponses();
    JSONArray children = new JSONArray();
    getDocEntry(name,children);//this add all doc that has the fieldwith the same value name to children
    if (responses.getCount() > 0) {
        Document docResponse = responses.getFirstDocument();

        while (docResponse != null) {
            children.add(getJsonDocAndChildren(docResponse));
            Document docTemp = responses.getNextDocument(docResponse);
            docResponse.recycle();
            docResponse = docTemp;
        }

    }
    jsonDoc.put("children", children);
    return jsonDoc;
}

2 个答案:

答案 0 :(得分:1)

这里有一些东西,从一般效率到基于你想要如何使用代码的优化。

可能加速处理的最大问题是只进行查看操作,而不会破解文档。由于您希望不加选择地获得响应,因此可以将响应文档添加到原始视图中,并打开“在层次结构中显示响应”选项。然后,如果您在视图中有Namefield列(并且没有“仅显示回复”)列,那么沿着视图向下走nav.getNext()将依次获取它们。通过存储每个先前条目的entry.getIndentLevel()值并在循环开始时进行比较,您可以在JSON树上“上下”:当缩进级别增加1时,创建一个新数组并添加它对现有的对象;当它减少时,加强一个。一开始它可能有点概念上的尴尬,不得不在平坦循环中跟踪先前的状态,但它会更有效率。

另一个选项,也是不必破解每个单独文档的好处,是查看按@Text($REF)分类的响应文档,然后使您的递归方法看起来更像:

public static void walkTree(final View treeView, final String documentId) {
    ViewNavigator nav = treeView.createViewNavFromCategory(documentId);
    nav.setBufferMaxEntries(400);
    for (ViewEntry entry : nav) {
        // Do code here

        walkTree(treeView, entry.getUniversalID(), callback);
    }
}

(该示例使用OpenNTF Domino API,但是,如果您不使用它,则可以将for循环下转换为传统样式)

作为一个小改进,只要您遍历ViewNavigators,就可以设置view.setAutoUpdate(false)然后nav.setBufferMaxEntries(400)来改进内部缓存。

最后,根据您的需求 - 例如,如果您将JSON直接输出到HTTP响应的输出流 - 您可以使用JsonWriter代替JsonObject来流式传输内容而不是在内存中构建一个巨大的对象。我在这里用一些简单的代码写了它:https://frostillic.us/blog/posts/EF0B875453B3CFC285257D570072F78F

答案 1 :(得分:1)

您应首先确定代码中花费的时间。也许它在doc.getResponses()responses.getNextDocument()中,您没有在此处显示。

可以在您的代码段中进行的明显优化如下:

基本上你有一些名为Document的数据结构,并构建一个由JSONObjects和JSONArrays组成的内存JSON结构。然后将此JSON结构序列化为String并返回。

您可以直接使用JsonWriter而不是构建JSON结构(不知道您正在使用什么JSON库,但必须有类似JsonWriter的东西)。这避免了临时JSON结构的内存分配。

getJson()开始:

StringWriter stringOut = new StringWriter();
JsonWriter out = new JsonWriter(stringOut);

并结束

return stringOut.toString();

现在,无论您在哪里创建JSONObjects或JSONArrays,都可以调用相应的编写器方法。 e.g。

private void getJsonDocAndChildren(Document doc, JsonWriter out) throws NotesException {
     out.name("name");
     out.value(doc.getItemValueString("Name"));
     out.name("field");
     out.value(doc.getItemValueString("field"));
     DocumentCollection responses = doc.getResponses();
     if (responses.getCount() > 0) {
          Document docResponse = responses.getFirstDocument();
          out.startArray();
          ...

希望你明白这一点。