【问题标题】:WebView2 - Convert HTML Tbody To A Collection Using JSONWebView2 - 使用 JSON 将 HTML Tbody 转换为集合
【发布时间】:2021-04-28 14:51:40
【问题描述】:

我的 HTML 页面中有一个表格,需要发送给主机。我使用ExecuteScriptAsync 方法(WebView2)来做到这一点。该方法返回一个 Newtonsoft.Json.Linq.JObject 作为结果。它看起来像这样 {{ "1": {}, "2": {}, "3": {}, "4": {}, "5": {}, "6": {}, "7": {} }} 。行数是正确的,但如您所见,您没有对该表的完全访问权限。

反序列化 JObject 以获取表的正确方法是什么

JsonConvert.DeserializeObject<object>(await this.WebView2Form.ExecuteScriptAsync("document.getElementById('" + TABLEID + "')." + rows));

也就是说,我需要执行下面的 javascript 并且能够在 C# 中读取结果

document.getElementById("myTable").rows

【问题讨论】:

  • 使用 Newtonsoft 在 C# 中反序列化 HTML 表的正确方法是什么? -- Json.NET 用于解析 JSON 而不是 HTML,没有正确的方法来使用 Newtonsoft反序列化HTML table。或者,也许您在 HTML 中嵌入了一个 JSON 数组,您想用 Newtonsoft 进行解析?如果是这样,请edit您的问题分享minimal reproducible example,显示您尝试解析的JSON字符串——即await this.WebView2Form.ExecuteScriptAsync("document.getElementById('" + TABLEID + "')." + rows返回的字符串

标签: json.net webview2


【解决方案1】:

好吧,@David Risney 解释得很好,为什么不能将 HTMLCollectionrows 属性返回的内容)序列化为 JSON。

您可以改为编写一个返回二维数组的 javascript 函数,该函数将自动序列化为 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]

【讨论】:

  • 我创建了自己的 javascript 函数并从主机调用它。你的想法就像一个魅力
【解决方案2】:

ExecuteScriptAsync 使用 JSON.stringify 将脚本执行的结果序列化为 JSON。在浏览器中,如果您导航到带有类似 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 确实序列化了所有继承的属性,如果你给它一个表格行 DOM 对象,它会抛出,因为它有一个 ownerDocument 属性。 ownerDocument 是包含文档,可让您获取其子项并最终返回表行 DOM 元素,这是 JSON.stringify 不允许的循环引用。

【讨论】:

  • 再次感谢大卫的精彩解释。它有很大帮助。我终于创建了一个 javascript 函数,它返回一个基于 HTML 表的数组。该功能需要立即生效。我将脚本设置为 ExecuteScriptAsync 的参数,它为我返回了表格。
猜你喜欢
  • 2022-01-25
  • 1970-01-01
  • 2019-02-25
  • 1970-01-01
  • 2013-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多