Serialization and deserialization in .NET applications can be achieved using several libraries, e.g.
Newtonsoft.Json
System.Text.Json
Assuming I'm developing a new application where I want to use Newtonsoft.Json
but I want to keep the flexibility to switch to System.Text.Json
(or another library) at a later point in time (e.g. in the hypothetical scenario that System.Text.Json
doesn't currently support certain features I need but it will in future):
Would it make sense to work with an interface and inject it wherever I need to serialize / deserialize something, so that once I want to switch the library, I can simply implement a new class and resolve the dependency accordingly at a centralized point of my application?
Sample code:
Interface:
public interface ISerializer
{
string SerializeObject<T>(T obj);
T DeserializeObject<T>(string str);
}
Implementation with Newtonsoft.Json
public class NewtonsoftJsonSerializer : ISerializer
{
public string SerializeObject<T>(T obj)
{
try
{
return JsonConvert.SerializeObject(obj);
}
catch (JsonException e)
{
throw new InvalidOperationException("Serialization failed.", e);
}
}
public T DeserializeObject<T>(string str)
{
try
{
return JsonConvert.DeserializeObject<T>(str);
}
catch (JsonException e)
{
throw new InvalidOperationException("Deserialization failed.", e);
}
}
}
Implementation with System.Text.Json
public class SystemTextJsonSerializer : ISerializer
{
public string SerializeObject<T>(T obj)
{
try
{
return JsonSerializer.Serialize(obj);
}
catch (JsonException e)
{
throw new InvalidOperationException("Serialization failed.", e);
}
}
public T DeserializeObject<T>(string str)
{
try
{
return JsonSerializer.Deserialize<T>(str);
}
catch (JsonException e)
{
throw new InvalidOperationException("Deserialization failed.", e);
}
}
}
I realize that this may seem a bit fussy, but it seems like a good idea to replace the implementation in a simple way in a single place (in the dependency resolution) without having to replace namespaces and method calls in many classes.
This procedure could also be useful if, for example, you want to switch from XML serialization to JSON serialization.
[Attributes]
that only one of them supports. This isn't necessarily a problem. You don't have to make everything perfectly dynamic and flexible, because if your requirements change in the future then you can still edit your code (as long as you control deployment and all dependents).