使用Json.Net ContractResolver和内部引用属性

时间:2013-09-14 04:22:02

标签: c# json rest json.net

在编写API时,我们遇到了过滤掉请求用户无权访问的模型属性的要求。

使用Json.Net ContractResolver,我们能够在很大程度上解决这个问题。

public class ConverterContractResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, Newtonsoft.Json.MemberSerialization memberSerialization)
    {
        //filter the properties and return back the final list
    }
}

然而,在参考属性急切加载的情况下,ContactResolver似乎无效。 例如,对于以下类:

public class Contact
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string AccountId { get; set; }
    public Account Account { get; set; }
}
public class Account 
{
   public int Id { get; set; }
   public string Name { get; set; }
   public string Website { get; set; }
   public string BillingAddress { get; set; }
}

当查询联系人时,可能急切地加载帐户记录,当序列化为JSON时,ContractResolver将仅在联系人字段而不是帐户字段上应用过滤器。

Contact data = new Contact { 
    FirstName = "John",
    LastName = "Duo",
    AccountId = 123,
    Account = new Account { Id=123, Name="My Company", Website="www.mycompany.com" }
};
string json = Newtonsoft.Json.JsonConvert.SerializeObject(data, 
     Newtonsoft.Json.Formatting.Indented,
     new JsonSerializerSettings { 
       ContractResolver= new ConverterContractResolver() 
     });

有没有办法让Json.net为参考属性调用相同的合约解析器?

1 个答案:

答案 0 :(得分:2)

最终我发现在我的模型中每个引用的对象都会调用ContractResolver。 这部分是好的,但有点问题,因为它只传递被解析的对象的类型为JSON,没有关于深度或找到对象的位置的信息。

public class ConverterContractResolver : DefaultContractResolver
{
     protected override IList<JsonProperty> CreateProperties(Type type, 
                   Newtonsoft.Json.MemberSerialization memberSerialization)
     {
         //filter the properties and return back the final list
     }
}

通过添加一个计数器来调用CreateProperties的次数,我设法识别哪个调用是针对主模型的,哪个后续调用是针对引用的对象。

这部分解决了我的问题,现在相同的ContractorResolver将过滤应用于模型中的所有引用对象。