question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Add JsonSerializer.Clone method

See original GitHub issue

I’m currently using the following extension method to clone json serializable types.

public static T Clone<T>(this JsonSerializer jsonSerializer, T value)
{
    var objectType = value?.GetType();
    using (var ms = new MemoryStream())
    {
        using (var sw = new StreamWriter(ms, new UTF8Encoding(false), 256, true))
        {
            jsonSerializer.Serialize(sw, value);
        }
        ms.Position = 0;
        using (var sr = new StreamReader(ms))
        {
            return (T)jsonSerializer.Deserialize(sr, objectType);
        }
    }
}

While this method works pretty well it does suffer from fully serializing the type to the MemoryStream before deserializing it. It would be much better if it could serialize the value as required from TextReader.Read calls.

I tried to implement this through a push-based TextReader that would cause the JsonSerializer to only serialize the requested read amount of characters on demand through calls to a push-based TextWriter but there was no way for me to partially serialize the value and unwind the call stack to return only the requested amount of characters.

It seems to me this functionality would have to be implemented directly in Json.NET to prevent the potentially large memory allocation of fully serializing to a MemoryStream before deserializing.

Proposed API

 namespace Newtonsoft.Json {
     public class JsonSerializer {
+        public T Clone<T>(T value);
     }
     public static class JsonConvert {
+        public T Clone<T>(T value);
+        public T Clone<T>(T value, JsonSerializerSettings settings);
+        public T Clone<T>(T value, params JsonConverter[] converters);
     }
 }

Issue Analytics

  • State:open
  • Created 6 years ago
  • Reactions:5
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
TylerBrinkleycommented, Jan 9, 2018

The recommended deep cloning method for C# is to serialize and deserialize that object. See StackOverflow for the recommended use of BinaryFormatter or Json.NET. This solution is not specific to .NET either as it’s also recommended in JavaScript. While Json.NET is a Json library it seems to be very commonly used for cloning and may warrant the additional methods, especially with the potential performance improvement.

0reactions
TylerBrinkleycommented, Jan 9, 2018

If you’d want to support preserving references between the value and the cloned value so that it’s not necessarily a complete deep clone, there should be added a setting to check for a reference regardless of if it’s contract specifies as IsReference. That would allow the following unit test to pass.

var value = new { Dictionary = new Dictionary<string, int>
{
    { "abc", 123 },
    { "def", 456 }
}};
var referenceResolver = new DefaultReferenceResolver();
referenceResolver.GetReference(null, value.Dictionary);
var b = JsonConvert.Clone(a, new JsonSerializerSettings { ReferenceResolverProvider = () => referenceResolver });
Assert.AreNotSame(a, b);
Assert.AreSame(a.Dictionary, b.Dictionary);
Read more comments on GitHub >

github_iconTop Results From Across the Web

Copy JsonSerializerSettings from JsonSerializer to new ...
Seems like the best way is to just copy all the settings into a new object. There are a ton of them, so...
Read more >
How to Clone Objects in C# .NET Core
If serializing the object to JSON, use the Microsoft.AspNetCore.Mvc.NewtonsoftJson Nuget package since the built-in JSON serializer that comes ...
Read more >
How to instantiate JsonSerializerOptions with System.Text. ...
Serialize or JsonSerializer.Deserialize. It's safe to use the same instance across multiple threads. The metadata caches on the options instance ...
Read more >
Cloning Objects In C# .NET - NET Core Tutorials
Binary Serializer Cloning ... An exceptionally common way of doing deep clones (Or atleast, more than just a shallow clone) is by serialising...
Read more >
Clone( ) method (JsonObject) - Progress Documentation
Creates a copy of a JsonObject instance and returns an object reference to the new instance. Return type: Progress.Lang.Object class Access: PUBLIC Applies ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found