1

I'm using Newtonsoft.JSON and I have a JSON array where each array member is itself an array of two numbers, e.g.

{
    "objList": [
        [8.8, 4],
        [9.2, 1.45],
        [1.61, 32.79]
    ]
}

I want to deserialize this into a class MyObjList defined by

public class MyObjList {
    [DataMember(Name = "objList")]
    public List<MyObj> ObjList { get; set; }
}

where MyObj is the class

public class MyObj {
    public double FirstDouble{ get; set; }
    public double SecondDouble { get; set; }
}

I knew that more work was required, but just tying the above gave me a helpful error message that told me that I could put [JsonArrayAttribute] on the MyObj class, i.e.

[JsonArrayAttribute]
public class MyObj{
    public double FirstDouble{ get; set; }
    public double SecondDouble { get; set; }
}

That has moved things on and the deserializer now fails at the next stage where it's looking for a suitable constructor. But I don't know how to write the constructor that is required and I can't find any examples. Can someone tell me how to do it?

Tolga Evcimen
  • 7,112
  • 11
  • 58
  • 91
Stochastically
  • 7,616
  • 5
  • 30
  • 58

3 Answers3

1

The JSON you have, does not represent you object MyObjList.

{
    "objList": [
        [8.8, 4],
        [9.2, 1.45],
        [1.61, 32.79]
    ]
}

Your JSON is basically a List<List<double>>.

One easy way to create your object out of this data, is to use Linq-to-JSON from Json.NET and construct your object like this

var jsonString = @"{ ""objList"": [ [8.8, 4], [9.2, 1.45], [1.61, 32.79] ] }";
var jObject = JObject.Parse(jsonString);

var myObjList = new MyObjList
{
    ObjList = jObject["objList"]
                .ToObject<List<List<double>>>()
                .Select(list => new MyObj { FirstDouble = list[0], SecondDouble = list[1] })
                .ToList()
};

See the documentation for more details.

Arghya C
  • 9,805
  • 2
  • 47
  • 66
  • Your answer suggests that all I need to do is to put a constructor `public MyObj(List list){}` onto my object. If that's right, presumably I would need to decorate that constructor somehow? – Stochastically Dec 16 '15 at 14:38
  • There should be a way to do that, but I'm not sure what `Attribute` to use. You might need to write some custom `JsonConverter`. – Arghya C Dec 16 '15 at 15:16
1

If you're keen on using MyObj instead of List<double>, you could try by creating a custom JsonConverter for your MyObj type — which basically just wraps the whole List<double> deserialization and feeding it to the MyObj type — like this:

[JsonConverter(typeof(MyObjConverter))]
public class MyObj{
  public double FirstDouble{ get; set; }
  public double SecondDouble { get; set; }
}

public class MyObjConverter : JsonConverter
{
  public override bool CanWrite { get { return false; } }

  public override bool CanConvert(Type objectType) {
    return objectType == typeof(MyObj);     
  }

  public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {                
    var doubles = serializer.Deserialize<List<double>>(reader);
    return new MyObj { FirstDouble = doubles[0], SecondDouble = doubles[1] };                       
  }

  public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
    throw new NotImplementedException();
  }
}

Demo: https://dotnetfiddle.net/x0FCFX

IronGeek
  • 4,764
  • 25
  • 27
  • Thanks, that's exactly what I was looking for :-). FYI, I was able to make the JsonArrayAttribute method work, but only by implementing the IList interface on the class MyObj which was far from ideal! – Stochastically Dec 16 '15 at 16:21
0

Don't know if it is a requirement mapping your doubles into a actual class like that. I think doing that would only complicate things. This is the simplest way to get it working:

MyObjList

public class MyObjList
{
   public List<List<double>> objList { get; set; }
}

And in a POST you will get this:

POST

jpgrassi
  • 5,482
  • 2
  • 36
  • 55