WebView2 - 使用 JSON 将 HTML Tbody 转换为集合
WebView2 - Convert HTML Tbody To A Collection Using JSON
我的 HTML 页面中有一个 table 需要发送给主机。我使用 ExecuteScriptAsync
方法 (WebView2) 来做到这一点。那个方法returns一个Newtonsoft.Json.Linq.JObject结果。它看起来像这样 {{ "1": {}, "2": {}, "3": {}, "4": {}, "5": {}, "6": {}, "7": {} }}
。行数是正确的,但如您所见,您没有对 table.
的完全访问权限
反序列化 JObject 以获得 table
的正确方法是什么
JsonConvert.DeserializeObject<object>(await this.WebView2Form.ExecuteScriptAsync("document.getElementById('" + TABLEID + "')." + rows));
换句话说,我需要执行下面的javascript并且能够在C#中读取结果
document.getElementById("myTable").rows
ExecuteScriptAsync 使用 JSON.stringify 将脚本执行的结果序列化为 JSON。在您的浏览器中,如果您导航到带有 table 的页面,例如 https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table,然后打开 DevTools 和 运行 以下内容,您会看到相同类型的结果:
JSON.stringify(document.getElementById("perfCardTable").rows)
"{\"0\":{},\"1\":{},\"2\":{},\"3\":{},\"4\":{}}"
问题是 JSON.stringify 仅直接在对象上序列化 hasOwnProperty 属性,而不是从其父对象原型继承的属性。几乎每个 DOM 对象都从其父对象继承其所有属性,因此您会看到 {}
作为任何 DOM 对象的 JSON.stringify 的结果。
要解决此问题,您可以将您关心的属性直接复制到新对象上。
JSON.stringify(Array.from(document.getElementById("perfCardTable").rows).map(row => {
let copy = {};
for (let name in row) {
copy[name] = row[name];
}
return copy;
}));
这样做的结果非常大,并且只处理行上的属性而不是那些属性的属性,因此您可能希望挑选出您感兴趣的特定属性,而不是复制所有内容。
顺便说一句,如果 JSON.stringify 确实序列化了所有继承的属性,如果您给它一个 table 行 DOM 对象,它就会抛出异常,因为它有一个 ownerDocument 属性。 ownerDocument 是包含文档,它允许您获取其子项并最终返回到您的 table 行 DOM 元素,这是 JSON.stringify.
不允许的循环引用
嗯,@David Risney 解释得很好,为什么你不能将 HTMLCollection
(rows
属性 returns)序列化为 JSON.
您可以改为编写一个 javascript 函数,该函数 returns 一个二维数组,它将自动序列化为 JSON 并轻松反序列化回二维数组C# 中的数组。
我假设您想将所有单元格的文本作为数组读取。
这样的函数在这里:
var TableContent = function (tableId)
{
let array = [];
/** @type {NodeListOf<HTMLTableRowElement>} */
let rows = document.querySelectorAll('#' + tableId + ' > tbody > tr');
rows.forEach(function (row, i, rows)
{
array[i] = [];
Array.from(row.cells).forEach(function (cell, j, cells)
{
array[i][j] = cell.textContent;
});
});
return array;
};
(你知道如何将 javascript 注入 WebView2
)。
现在在 C# 中很容易获得数组:
string tableId = "GridView1";
string json = await webView21.ExecuteScriptAsync("TableContent('" + tableId + "')");
string[][] cellsContent = Newtonsoft.Json.JsonConvert.DeserializeObject<string[][]>(json);
现在你有一个包含所有单元格文本的二维字符串数组。
您可以这样访问:
cellsContent[rowIndex][cellIndex]
我的 HTML 页面中有一个 table 需要发送给主机。我使用 ExecuteScriptAsync
方法 (WebView2) 来做到这一点。那个方法returns一个Newtonsoft.Json.Linq.JObject结果。它看起来像这样 {{ "1": {}, "2": {}, "3": {}, "4": {}, "5": {}, "6": {}, "7": {} }}
。行数是正确的,但如您所见,您没有对 table.
反序列化 JObject 以获得 table
的正确方法是什么JsonConvert.DeserializeObject<object>(await this.WebView2Form.ExecuteScriptAsync("document.getElementById('" + TABLEID + "')." + rows));
换句话说,我需要执行下面的javascript并且能够在C#中读取结果
document.getElementById("myTable").rows
ExecuteScriptAsync 使用 JSON.stringify 将脚本执行的结果序列化为 JSON。在您的浏览器中,如果您导航到带有 table 的页面,例如 https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table,然后打开 DevTools 和 运行 以下内容,您会看到相同类型的结果:
JSON.stringify(document.getElementById("perfCardTable").rows)
"{\"0\":{},\"1\":{},\"2\":{},\"3\":{},\"4\":{}}"
问题是 JSON.stringify 仅直接在对象上序列化 hasOwnProperty 属性,而不是从其父对象原型继承的属性。几乎每个 DOM 对象都从其父对象继承其所有属性,因此您会看到 {}
作为任何 DOM 对象的 JSON.stringify 的结果。
要解决此问题,您可以将您关心的属性直接复制到新对象上。
JSON.stringify(Array.from(document.getElementById("perfCardTable").rows).map(row => {
let copy = {};
for (let name in row) {
copy[name] = row[name];
}
return copy;
}));
这样做的结果非常大,并且只处理行上的属性而不是那些属性的属性,因此您可能希望挑选出您感兴趣的特定属性,而不是复制所有内容。
顺便说一句,如果 JSON.stringify 确实序列化了所有继承的属性,如果您给它一个 table 行 DOM 对象,它就会抛出异常,因为它有一个 ownerDocument 属性。 ownerDocument 是包含文档,它允许您获取其子项并最终返回到您的 table 行 DOM 元素,这是 JSON.stringify.
不允许的循环引用嗯,@David Risney 解释得很好,为什么你不能将 HTMLCollection
(rows
属性 returns)序列化为 JSON.
您可以改为编写一个 javascript 函数,该函数 returns 一个二维数组,它将自动序列化为 JSON 并轻松反序列化回二维数组C# 中的数组。
我假设您想将所有单元格的文本作为数组读取。
这样的函数在这里:
var TableContent = function (tableId)
{
let array = [];
/** @type {NodeListOf<HTMLTableRowElement>} */
let rows = document.querySelectorAll('#' + tableId + ' > tbody > tr');
rows.forEach(function (row, i, rows)
{
array[i] = [];
Array.from(row.cells).forEach(function (cell, j, cells)
{
array[i][j] = cell.textContent;
});
});
return array;
};
(你知道如何将 javascript 注入 WebView2
)。
现在在 C# 中很容易获得数组:
string tableId = "GridView1";
string json = await webView21.ExecuteScriptAsync("TableContent('" + tableId + "')");
string[][] cellsContent = Newtonsoft.Json.JsonConvert.DeserializeObject<string[][]>(json);
现在你有一个包含所有单元格文本的二维字符串数组。
您可以这样访问:
cellsContent[rowIndex][cellIndex]