Search code examples
c#json.netjson-deserialization

Deserialize List<Object> using NewtonSoft. Cannot convert IList


I am trying to parse a List of Comment objects from here. A comment object is a class in the leankit namespace: LeanKit.API.Client.Library.TransferObjects.Comment but I get an error in the final line of the block below specifically over responseString:

cannot convert from 'System.Collections.Generic.IList' to string

Why am I getting this? I am specifying a custom class I created specifically to deserialize the list:

public class MyCommentList
{
    public string ReplyText { get; set; }
    public List<Comment> ReplyData { get; set; }
    public string ReplyCode { get; set; }
} 

calling the class

var url = "https://" + acctName + ".leankit.com/kanban/api/card/getcomments/" + boardid + "/" + cardid;
var responseString = await url.WithBasicAuth("xxx", "yyy").GetJsonListAsync();
MyCommentList mycomment = JsonConvert.DeserializeObject<MyCommentList>(responseString);

a cleaner version of calling the class (using Flurl):

var url = "https://" + acctName + ".leankit.com/kanban/api/card/getcomments/" + boardid + "/" + cardid;
MyCommentList mycomment = await url.WithBasicAuth("xxx", "yyy").GetAsync().ReceiveJson<MyCommentList>();

The JSON structure (from the link above) reproduced here:

{
  "ReplyData": [
    [
      {
        "Id": 256487698,
        "Text": "First comment for this card.",
        "TaggedUsers": null,
        "PostDate": "10/14/2015 at 04:36:02 PM",
        "PostedByGravatarLink": "3ab1249be442027903e1180025340b3f",
        "PostedById": 62984826,
        "PostedByFullName": "David Neal",
        "Editable": true
      }
    ]
  ],
  "ReplyCode": 200,
  "ReplyText": "Card comments successfully retrieved."
}

Solution

  • In the JSON, "ReplyData" is a 2d jagged array:

    {
      "ReplyData": [ [ ... ] ],
    }
    

    In you model it is a 1d list:

    public List<Comment> ReplyData { get; set; }.  
    

    You need to change it to public List<List<Comment>> ReplyData { get; set; } to reflect the actual JSON:

    public class MyCommentList
    {
        public string ReplyText { get; set; }
        public List<List<Comment>> ReplyData { get; set; }
        public string ReplyCode { get; set; }
    } 
    

    Where I assume Comment is taken from https://github.com/LeanKit/LeanKit.API.Client/blob/master/LeanKit.API.Client.Library/TransferObjects/Comment.cs.

    If there is a chance that it is sometimes a 1d array and sometimes a 2d array, you may need to apply SingleOrArrayConverter<Comment> from this answer to How to handle both a single item and an array for the same property using JSON.net by Brian Rogers like so:

    public class MyCommentList
    {
        public string ReplyText { get; set; }
    
        [JsonProperty(ItemConverterType = typeof(SingleOrArrayConverter<Comment>))]
        public List<List<Comment>> ReplyData { get; set; }
        public string ReplyCode { get; set; }
    } 
    

    Working sample .Net fiddle here.