0

新的可变JsonNode类型既没有 aClone()也没有复制构造函数。我怎样才能复制一个?

我尝试使用 复制一个浅层 JsonObject(一个填充原始键值对)new JsonObject(original),但即使这样也不起作用(它会抛出InvalidOperationException,因为 aJsonNode不能在两个 JSON 树之间共享)。

4

1 回答 1

0

您可以通过将其转换为 JSON 并将其转换回JsonNode.

快速而肮脏的方式:

var copy = JsonNode.Parse(original.ToJsonString());

需要注意的是,JsonNode 以 UTF-8 格式读取和写入 JSON,因此这种方法效率低下,部分原因是它会转换为 UTF-16 并返回(部分原因是它是解析,我们似乎无法避免)。这是一个更有效的方法:

public static JsonNode? Clone(this JsonNode? node) {
    if (node == null)
        return null;

    // Yes, we're creating three garbage objects (array + two writers) but
    // the alternative `JsonNode.Parse(original.ToJsonString())` is worse.
    var buf = new ArrayBufferWriter<byte>(512);
    var jwriter = new Utf8JsonWriter(buf);
    node.WriteTo(jwriter);
    jwriter.Flush(); // I don't know why this is necessary, but it is
    return JsonNode.Parse(buf.WrittenSpan);
}

[return: NotNullIfNotNull("node")]
public static JsonObject? Clone(this JsonObject? node)
    => (JsonObject?) Clone((JsonNode) node);

[return: NotNullIfNotNull("node")]
public static JsonArray? Clone(this JsonArray? node)
    => (JsonArray?) Clone((JsonNode)node);

(这确实缺少 使用的数组池优化ToJsonString,它依赖于我们无权访问的内部类。它仍然更好。)


单元测试:

[Test]
public void JsonNodeCloneTest()
{
    var json = JsonNode.Parse(@"{
        ""A"": 12345.67890,
        ""B"": [ ""string"", false, true, null, { ""N"": ""no"" } ]
    }")!;
    var jsonString1 = json.ToJsonString();
            
    var json2 = json.Clone(); // method under test
            
    var jsonString2 = json2.ToJsonString();

    Assert.AreEqual(jsonString1, jsonString2);
}
于 2022-02-05T17:04:44.047 回答