使用不可变对象检测构造函数参数名称和属性名称之间的不匹配

时间:2018-05-24 13:22:44

标签: c# json.net deserialization immutability

考虑以下可变对象:

class SomePoco
{
    public int Id{get;set;}
    public string Name{get;set;}
}

让我们通过Json.NET进行往返:

var p=new SomePoco{Id=4,Name="spender"};
var json=JsonConvert.SerializeObject(p);
var pr = JsonConvert.DeserializeObject<SomePoco>(json);
Console.WriteLine($"Id:{pr.Id}, Name:{pr.Name}");

一切都很好。

现在,让我们通过构造函数使POCO不可变并提供值:

class SomeImmutablePoco
{
    public SomeImmutablePoco(int id, string name)
    {
        Id = id;
        Name = name;
    }
    public int Id{get;}
    public string Name{get;}
}

...再次往返数据:

var p = new SomeImmutablePoco(5, "spender's immutable friend");
var json = JsonConvert.SerializeObject(p);
var pr = JsonConvert.DeserializeObject<SomeImmutablePoco>(json);
Console.WriteLine($"Id:{pr.Id}, Name:{pr.Name}");

还不错。

现在,让我们通过重命名构造函数参数对我们的不可变类进行一些小改动:

class SomeImmutablePoco
{
    public SomeImmutablePoco(int pocoId, string name)
    {
        Id = pocoId;
        Name = name;
    }
    public int Id{get;}
    public string Name{get;}
}

然后:

var p = new SomeImmutablePoco(666, "diabolo");
var json = JsonConvert.SerializeObject(p);
var pr = JsonConvert.DeserializeObject<SomeImmutablePoco>(json);
Console.WriteLine($"Id:{pr.Id}, Name:{pr.Name}");

哦亲爱的...看起来Json.NET对我们的构造函数参数的名称做了一些反思,并将它们与我们的POCO / json中的属性名称相匹配。这意味着我们刚刚反序列化的对象没有为其分配Id。当我们打印Id时,它是0

这很糟糕,追踪特别麻烦。

此问题可能存在于大量POCO中。如何自动查找这些问题POCO类?

2 个答案:

答案 0 :(得分:1)

以下是使用反射查找此类的代码:

var types = new List<Type>() { typeof(SomeImmutablePoco) }; // get all types using reflection
foreach (var type in types)
{
    var props = type.GetProperties(bindingAttr: System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
    foreach (var ctor in type.GetConstructors())
    {
        foreach (var param in ctor.GetParameters())
        {
            if (!props.Select(prop => prop.Name.ToLower()).Contains(param.Name.ToLower()))
            {
                Console.WriteLine($"The type {type.FullName} may have problems with Deserialization");
            }
        }
    }
}

答案 1 :(得分:0)

您可以像这样映射您的json属性:

class SomeImmutablePoco
    {
        public SomeImmutablePoco(int pocoId, string name)
        {


       Id = pocoId;
        Name = name;
    }

    [JsonProperty("pocoId")]
    public int Id { get; }
    public string Name { get; }
}