使用可为空的嵌套列表序列化对象

时间:2016-07-01 21:46:28

标签: c# json serialization

我有以下要序列化的对象:

class Account
{
    public Account(List<string> groups)
    {
        Groups = groups.Select(s=>new Group(s)).ToList();
    }
    [JsonProperty("Groups")]
    public List<Group> Groups { get; set; }
}
class Group
{
    public Group(string url)
    {
        Url = url;
    }

    public CommentSchedule NextCommentSchedule()
    {
        if (CommentSchedules.Count == 0) return null;
        return CommentSchedules.Aggregate((curMin, x) => x.StartTime < curMin.StartTime ? x : curMin); // Result of inside function goes to curMin, next item in list goes to x
    }

    [JsonProperty("Url")] 
    public string Url { get; set; }

    [JsonProperty("Comments")]
    public List<Comment> Comments { get; set; }

    [JsonProperty("CommentSchedules")]
    public List<CommentSchedule> CommentSchedules { get; set; }
}
class Comment
{
    public Comment(string text, int max)
    {
        Text = text;
        MaxPosts = max;
    }
    [JsonProperty("Text")] // Text to post
    public string Text { get; set; }

    [JsonProperty("MaxPosts")] // Maximum number of times comment can be posted before being removed
    public int MaxPosts { get; set; }
}

我将它反序列化到我正在保存的文件中没有问题,并且我可以在没有组时序列化字符串,但是当我尝试在添加组后序列化json字符串时我得到

  

解析值时遇到意外的字符:{。路径'组',第1行,第67位。

我很确定这是因为我用组内的空列表保存它所以当它尝试序列化空嵌套列表时它不喜欢它。我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

问题与您的Account类没有公共无参数构造函数有关。相反,它有一个参数化的构造函数,如下所示:

class Account
{
    public Account(List<string> groups)
    {
        Groups = groups.Select(s=>new Group(s)).ToList();
    }
    [JsonProperty("Groups")]
    public List<Group> Groups { get; set; }
}

当Json.NET尝试反序列化这样的类时,它将通过调用该构造函数构造一个类实例,使用反射按名称匹配JSON属性的构造函数参数并使用缺省值属性。按名称匹配是不区分大小写的,除非有多个匹配仅在大小写不同的情况下匹配,在这种情况下匹配将区分大小写。

现在,您的构造函数有一个名为groups的参数,其名称(模数为case)与属性Groups相同。 但是,它们是不同类型对象的集合。该属性返回映射到Json.NET 对象的类的集合,而构造函数则获取简单字符串的集合。这种不匹配会导致您看到序列化错误,因为Json.NET无法将对象反序列化为简单字符串。

解决方法是提供无参数构造函数或标记为[JsonConstructor]的参数化构造函数,并将List<Group> groups作为参数。只要构造函数标有[JsonConstructor],它们就可以是私有的。即要么添加:

    [JsonConstructor]
    Account()
    {
        Groups = new List<Group>();
    }

    [JsonConstructor]
    Account(List<Group> groups)
    {
        Groups = groups;
    }

您的Comment类只有参数化构造函数这一事实不是问题,因为参数的数据类型与其属性的数据类型相匹配。您可能希望将max参数的名称更改为maxPosts,以便将值传递给构造函数,而不是稍后通过属性设置:

    public Comment(string text, int maxPosts)
    {
        Text = text;
        MaxPosts = maxPosts;
    }

更一般地说,如果遵循惯例,您的构造函数参数应该具有相同的名称(模数情况)并且键入相应的类成员,那么Json.NET应该能够反序列化您的类。