XPages:从大量文档创建 JSON 字符串
XPages: Creating JSON String from large amount of document
我一直在尝试创建一个包含大量文档的 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;
}
这里有一些内容,从一般效率到基于您希望如何使用代码的优化。
可能会加快您的处理速度的主要方法是仅执行查看操作,而无需破解文档。由于看起来您想不加区别地获得响应,因此您可以将响应文档添加到原始视图,并打开 "Show responses in hierarchy" 选项。然后,如果您在视图中有 Name
和 field
的列(并且没有 "Show responses only")列,那么 nav.getNext()
沿着视图走会依次得到它们。通过存储每个先前条目的 entry.getIndentLevel()
值并在循环开始时比较它,您可以 "step" 在 JSON 树上上下移动:当缩进级别增加一个时,创建一个新数组并将其添加到现有对象;当它减少时,加强一个。起初在概念上可能有点尴尬,必须在一个平面循环中跟踪以前的状态,但它会更有效率。
另一种选择也具有不必打开每个单独文档的好处,即查看按 @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 循环向下转换为旧式)
作为每次遍历 ViewNavigator 时的小改进,您可以设置 view.setAutoUpdate(false)
,然后设置 nav.setBufferMaxEntries(400)
以改进内部缓存。
最后,根据您的需要 - 例如,如果您将 JSON 直接输出到 HTTP 响应的输出流 - 您可以使用 JsonWriter
而不是 JsonObject
将内容流出而不是在内存中构建一个巨大的对象。我在这里用一些简单的代码写了它:https://frostillic.us/blog/posts/EF0B875453B3CFC285257D570072F78F
您应该首先确定时间花在了代码中的什么地方。也许它在 doc.getResponses()
或 responses.getNextDocument()
中,您没有在此处显示。
可以在您的代码片段中完成的明显优化如下:
基本上你有一些称为文档的数据结构,并在内存中建立一个相应的 JSON 结构,由 JSON 对象和 JSON 数组组成。这个 JSON 结构随后被序列化为一个字符串并返回。
您可以直接使用 JsonWriter,而不是构建 JSON 结构(不知道您使用的是什么 JSON 库,但必须有类似 JsonWriter 的东西)。这避免了临时 JSON 结构的内存分配。
在getJson()
你开始:
StringWriter stringOut = new StringWriter();
JsonWriter out = new JsonWriter(stringOut);
结束
return stringOut.toString();
现在,在您创建 JSON 对象或 JSON 数组的任何地方,您都可以调用相应的编写器方法。例如
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();
...
希望你明白了。
我一直在尝试创建一个包含大量文档的 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;
}
这里有一些内容,从一般效率到基于您希望如何使用代码的优化。
可能会加快您的处理速度的主要方法是仅执行查看操作,而无需破解文档。由于看起来您想不加区别地获得响应,因此您可以将响应文档添加到原始视图,并打开 "Show responses in hierarchy" 选项。然后,如果您在视图中有 Name
和 field
的列(并且没有 "Show responses only")列,那么 nav.getNext()
沿着视图走会依次得到它们。通过存储每个先前条目的 entry.getIndentLevel()
值并在循环开始时比较它,您可以 "step" 在 JSON 树上上下移动:当缩进级别增加一个时,创建一个新数组并将其添加到现有对象;当它减少时,加强一个。起初在概念上可能有点尴尬,必须在一个平面循环中跟踪以前的状态,但它会更有效率。
另一种选择也具有不必打开每个单独文档的好处,即查看按 @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 循环向下转换为旧式)
作为每次遍历 ViewNavigator 时的小改进,您可以设置 view.setAutoUpdate(false)
,然后设置 nav.setBufferMaxEntries(400)
以改进内部缓存。
最后,根据您的需要 - 例如,如果您将 JSON 直接输出到 HTTP 响应的输出流 - 您可以使用 JsonWriter
而不是 JsonObject
将内容流出而不是在内存中构建一个巨大的对象。我在这里用一些简单的代码写了它:https://frostillic.us/blog/posts/EF0B875453B3CFC285257D570072F78F
您应该首先确定时间花在了代码中的什么地方。也许它在 doc.getResponses()
或 responses.getNextDocument()
中,您没有在此处显示。
可以在您的代码片段中完成的明显优化如下:
基本上你有一些称为文档的数据结构,并在内存中建立一个相应的 JSON 结构,由 JSON 对象和 JSON 数组组成。这个 JSON 结构随后被序列化为一个字符串并返回。
您可以直接使用 JsonWriter,而不是构建 JSON 结构(不知道您使用的是什么 JSON 库,但必须有类似 JsonWriter 的东西)。这避免了临时 JSON 结构的内存分配。
在getJson()
你开始:
StringWriter stringOut = new StringWriter();
JsonWriter out = new JsonWriter(stringOut);
结束
return stringOut.toString();
现在,在您创建 JSON 对象或 JSON 数组的任何地方,您都可以调用相应的编写器方法。例如
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();
...
希望你明白了。