A Lot of times, this is required in a lot of Classes when the project is bigger.
We need the conversion to work both ways. A class should be serialized using the ToString()
method, and the class should be deserialized from the String. We use the following convention.
Define marker interfaces to let classes explicitly adhere to the contract that they support Serialization using the ToString method and also support Deserialization from string to object instance.
/// <summary>
/// Interface to convert string to a type T
/// </summary>
public interface IStringToTypeConverter<out T>
{
T ConvertToType(string stringToConvertFrom);
}
/// <summary>
/// Marker Interface to let Serialization/Deserialization work on the ToString Method of the class, Rather than
/// calling on the Instance properties
/// </summary>
public interface ITypeToStringConverter
{
}
Next, Define the generic converter which will do the conversion (Serialization/Deserialization) for a class which implements the above interfaces.
public class ToStringJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
var isTypeImplementStringToTypeConverter = objectType.GetInterfaces().Any(x =>
x == typeof(ITypeToStringConverter) ||
(x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(IStringToTypeConverter<>)));
return isTypeImplementStringToTypeConverter;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
}
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// Load the JSON for the Result into a JObject
var stringValue = reader.Value.ToString();
if (string.IsNullOrWhiteSpace(stringValue))
{
var jObject = JObject.Load(reader);
stringValue = jObject.ToString();
}
MethodInfo parse = objectType.GetMethod("ConvertToType");
if (parse != null)
{
var destinationObject = Activator.CreateInstance(objectType,stringValue);
return parse.Invoke(destinationObject, new object[] { stringValue });
}
throw new JsonException($"The {objectType.Name} type does not have a public ConvertToType(string) method.");
}
}
Lastly, Add the Converter to the startup class, passing it in the JSON Options
services.AddMvc().AddJsonOptions(options =>
{
options.SerializerSettings.Converters.Add(new ToStringJsonConverter());
})
Note: Please test the performance benhmarks for your code to see if it has any impact on your performance SLA.