新的可变JsonNode
类型既没有 aClone()
也没有复制构造函数。我怎样才能复制一个?
我尝试使用 复制一个浅层 JsonObject
(一个填充原始键值对)new JsonObject(original)
,但即使这样也不起作用(它会抛出InvalidOperationException
,因为 aJsonNode
不能在两个 JSON 树之间共享)。
您可以通过将其转换为 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);
}