【问题标题】:Using Json.Net ContractResolver and inner reference properties使用 Json.Net ContractResolver 和内部引用属性
【发布时间】:2013-09-14 04:22:02
【问题描述】:

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

【问题讨论】:

    标签: c# json rest json.net


    【解决方案1】:

    最终我发现我的模型中的每个引用对象也调用了 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 将过滤应用于我的模型中的所有引用对象。

    【讨论】:

    • 如果联系人有两个相同类型“Account”的帐户属性并且您需要为这两个“Account”类型的对象过滤掉不同的属性会发生什么?
    猜你喜欢
    • 1970-01-01
    • 2013-12-29
    • 1970-01-01
    • 1970-01-01
    • 2015-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多