I am receiving data that looks like this from an online service provider:
{
  name: "test data",
  data: [
    [ "2017-05-31", 2388.33 ],
    [ "2017-04-30", 2358.84 ],
    [ "2017-03-31", 2366.82 ],
    [ "2017-02-28", 2329.91 ]
  ],
}       
I would like to parse it into an object that looks like this:
public class TestData
{
   public string Name;
   public List<Tuple<DateTime, double>> Data;
}
The only thing I have been able to find is how to parse an array of objects into a list of tulples, for example: Json.NET deserialization of Tuple<...> inside another type doesn't work?
Is there a way to write a custom converter that would handle this?
If anyone is interested in a more generic solution for ValueTuples
public class TupleConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var type = value.GetType();
        var array = new List<object>();
        FieldInfo fieldInfo;
        var i = 1;
        while ((fieldInfo = type.GetField($"Item{i++}")) != null)
            array.Add(fieldInfo.GetValue(value));
        serializer.Serialize(writer, array);
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var argTypes = objectType.GetGenericArguments();
        var array = serializer.Deserialize<JArray>(reader);
        var items = array.Select((a, index) => a.ToObject(argTypes[index])).ToArray();
        var constructor = objectType.GetConstructor(argTypes);
        return constructor.Invoke(items);
    }
    public override bool CanConvert(Type type)
    {
        return type.Name.StartsWith("ValueTuple`");
    }
}
Usage is as follows:
var settings = new JsonSerializerSettings();
settings.Converters.Add(new TupleConverter());
var list = new List<(DateTime, double)>
{
    (DateTime.Now, 7.5)
};
var json = JsonConvert.SerializeObject(list, settings);
var result = JsonConvert.DeserializeObject(json, list.GetType(), settings);
                        Rather than use tuples, I would create a class that is specific to the task. In this case your JSON data comes in as a list of lists of strings which is a bit awkward to deal with. One method would be to deserialise as List<List<string>> and then convert afterwards. For example, I would go with 3 classes like this:
public class IntermediateTestData
{
    public string Name;
    public List<List<string>> Data;
}
public class TestData
{
    public string Name;
    public IEnumerable<TestDataItem> Data;
}
public class TestDataItem
{
    public DateTime Date { get; set; }
    public double Value { get; set; }
}
Now deserialise like this:
var intermediate = JsonConvert.DeserializeObject<IntermediateTestData>(json);
var testData = new TestData
{
    Name = intermediate.Name,
    Data = intermediate.Data.Select(d => new TestDataItem
    {
        Date = DateTime.Parse(d[0]),
        Value = double.Parse(d[1])
    })
};
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With