Add JsonSerializer.Clone method
See original GitHub issueI’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:
- Created 6 years ago
- Reactions:5
- Comments:5 (5 by maintainers)
The recommended deep cloning method for C# is to serialize and deserialize that object. See StackOverflow for the recommended use of
BinaryFormatter
orJson.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.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.