I'm trying to use Newtonsoft.Json to serialize and deserialize a Dictionary<(int, int), MyClass>
. Because (int, int)
has to get serialized to a string, I have to provide a custom TypeConverter
to deserialize it back to a tuple:
public class Tuple2Converter<T1, T2> : TypeConverter {
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) {
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) {
var parts = Convert.ToString(value).Trim('(').Trim(')').Split(", ");
var item1 = (T1)TypeDescriptor.GetConverter(typeof(T1)).ConvertFromInvariantString(parts[0])!;
var item2 = (T2)TypeDescriptor.GetConverter(typeof(T2)).ConvertFromInvariantString(parts[1])!;
return (item1, item2);
}
}
// ...
TypeDescriptor.AddAttributes(typeof((int, int)), new TypeConverterAttribute(typeof(Tuple2Converter<int, int>)));
var resultingObject =
JsonConvert.DeserializeObject<Dictionary<(int Q, int R), HexWithMeta>>(dictString);
However, when deserializing I now get the error:
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.ValueTuple`2[System.Int32,System.Int32]' because the type requires a JSON string value to deserialize correctly. To fix this error either change the JSON to a JSON string value or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
It's trying to use the custom TypeConverter to convert another (int, int)
to a C# tuple, but this time, the tuple was serialized in a standard way (JSON object instead of string), because this tuple is one that exists on MyClass
, so it was serialized like:
"QR": {
"Item1": 0,
"Item2": 0
}
How can I get Newtonsoft.Json to use the custom TypeConverter when deserializing the string-encoded tuple on the Dictionary key, but not for any tuples contained within the Dictionary's serialized values?
Note that I am only globally binding my TypeConverter via TypeDescriptor.AddAttributes()
to get correct JSON serialization, I don't need to do it for other reasons.