-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support ability to DeepClone a JsonNode in order to recursively create a copy of all children nodes #54019
Comments
Tagging subscribers to this area: @eiriktsarpalis, @layomia Issue DetailsBackground and MotivationWritable JSON DOM API's are available as part of the .NET 6 private preview. However, the current API's do not support an ability to perform a deep clone (i.e. create a recursive copy of all children nodes). Including support for a DeepClone API enables the ability to take an input JsonNode, apply transforms or filters, and copy over subsets of the source object into a new JsonNode (which can then be used for further manipulation or for serialization). JSON.NET has an analogous API with the same name (DeepClone). An example using existing JSON.NET API's is here. A workaround, in the absence of a DeepClone API is to serialize the JsonNode into a string, and re-convert the same into a new JsonNode. However, a built-in DeepClone API can likely be made to perform better, and avoid the interim conversion into a string (and associated allocations). Proposed APInamespace System.Text.Json.Nodes
{
public class JsonNode {
+ public JsonNode DeepClone();
}
} Usage ExamplesBelow is an example of how the new DeepClone API can be used // some lines of code here
public string FilterAndSerialize(JsonObject data)
{
JsonObject newData = new JsonObject();
newData["Product"] = new JsonObject();
newData["Product"]["Eligibility"] = new JsonObject();
var predicates = new JsonArray();
newData["Product"]["Eligibility"]["Predicates"] = predicates;
foreach (var item in data["Product"]["Eligibility"]["Predicates"].AsArray())
{
if (item["Type"].GetValue<string>().Equals("ClaimsPredicate"))
{
predicates.Add(item.DeepClone());
}
}
return Serialize(newData);
} Alternative DesignsUse combination of ToJsonString & Parse APIs. However, performance would likely suffer due to the intermediate string conversion.
|
What would happen in the following scenario? public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
Person p = new Person() { Name = "Andy", Age = 50 };
JsonNode original = JsonValue.Create(p);
Person p2 = original.GetValue<Person>();
JsonNode cloned = original.DeepClone();
Person p3 = cloned.GetValue<Person>(); |
If we need to convert a .NET object into one of the Json DOM API objects, then I would have expected to use JsonObject.Create(p), or JsonObject.FromObject(p), or new JsonObject(p). Unclear about why JsonValue.Create is being used here. Could you please clarify the same? Not sure of the intention of the current JsonValue.Create API. I was expecting JsonValue to only be used for primitive Json data types like string, number, and possibly support some conversions into other primitives like dates/timestamps. |
My comment was intended to spark discussion of "what happens if the DOM contains an object which is not cloneable?" I'm not really advocating any particular course of action. If "it throws an exception" is the desired behavior - great! :) The main point was that I think this proposal needs to define the expected behavior even in the face of all of these edge cases. |
cc @steveharter |
As shown above, So if a
instead of just:
So I think the most obvious
|
Closing as duplicate of #56592. |
Background and Motivation
Writable JSON DOM API's are available as part of the .NET 6 private preview. However, the current API's do not support an ability to perform a deep clone (i.e. create a recursive copy of all children nodes).
Including support for a DeepClone API enables the ability to take an input JsonNode, apply transforms or filters, and copy over subsets of the source object into a new JsonNode (which can then be used for further manipulation or for serialization).
JSON.NET has an analogous API with the same name (DeepClone). An example using existing JSON.NET API's is here.
A workaround, in the absence of a DeepClone API is to serialize the JsonNode into a string, and re-convert the same into a new JsonNode. However, a built-in DeepClone API can likely be made to perform better, and avoid the interim conversion into a string (and associated allocations).
Proposed API
namespace System.Text.Json.Nodes { public class JsonNode { + public JsonNode DeepClone(); } }
Usage Examples
Below is an example of how the new DeepClone API can be used
Alternative Designs
Use combination of ToJsonString & Parse APIs. However, performance would likely suffer due to the intermediate string conversion.
The text was updated successfully, but these errors were encountered: