1

在编写我们的 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; }
}

查询联系人时,可能会立即加载 Account 记录,当序列化为 JSON 时,ContractResolver 将仅对 Contact 字段应用过滤器,而不是 Account 字段。

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 也为引用属性调用相同的 Contract Resolver?

4

1 回答 1

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 将过滤应用于我的模型中的所有引用对象。

于 2013-10-26T04:13:19.830 回答