4

I have a dictionary like this:

var dict1 = new Dictionary<(int, int), int);
dict1.add((1,2), 3);

That is serialized to a string using:

var s = JsonConvert.SerializeObject(dict1);
// s = "{\"(1,2)\":\"3\"}";

When trying to deserialize the string using:

var j = JsonConvert.DeserializeObject<Dictionary<(int, int), int>>(s);

I get an error like:

'Could not convert string '(1,2)' to dictionary key type 'System.ValueTuple`2[System.Int32,System.Int32]'. Create a TypeConverter to convert from the string to the key type object.

How can I deserialize my string into a tuple key? Using a custom object or a TypeConverter? If so, how?

1

1 Answer 1

6

First, you make yourself a TypeConverter for ValueTuples<T1,T2>

internal class ValueTupleConverter<T1, T2>
   : TypeConverter 
   where T1: struct where T2: struct
{
    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 elements = ((String)value).Split(new[] { '(', ',', ')'},
          StringSplitOptions.RemoveEmptyEntries);

        return (
            JsonConvert.DeserializeObject<T1>(elements.First()), 
            JsonConvert.DeserializeObject<T2>(elements.Last()));
    }
}

(Production code should be made more robust and efficient.)

Then, because you can't do the usual thing of applying the TypeConverter attribute at compile-time, you add it at run-time, once

  TypeDescriptor.AddAttributes(typeof((Int32, Int32)), 
    new TypeConverterAttribute(typeof(ValueTupleConverter<Int32, Int32>)));

Finally, you convert as you were doing

var j = JsonConvert.DeserializeObject<Dictionary<(int, int), int>>(s);
Sign up to request clarification or add additional context in comments.

1 Comment

Nice, added it to Program.cs with some extra error checking and it seems to work flawlessly.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.