Json.Net 自定义 ContractResolver 忽略自定义对象

Posted

技术标签:

【中文标题】Json.Net 自定义 ContractResolver 忽略自定义对象【英文标题】:Json.Net Custom ContractResolver Ignoring Custom Objects 【发布时间】:2021-10-09 02:29:03 【问题描述】:

在 Json.Net 中使用自定义 ContractResolver 时遇到一个非常奇怪的实例。

我的模型结构如下:

public class ParentClass

    public string Item1  get; set; 
    public CustomModel Item2  get; set; 


public class CustomModel

    public string CustomItem1  get; set; 
    public string CustomItem2  get; set; 


public class ChildClass : ParentClass

    public string Item3  get; set; 
    public string Item4  get; set; 

我的任务涉及创建一个仅包含 ParentClass 模型的序列化属性的 JSON 字符串,如下所示:


  "Item1": "abc",
  "Item2": 
    "CustomItem1": "def",
    "CustomItem2": "ghi"
  

因此,我创建了一个自定义合同解析器,如下所示:

public class CustomResolver : DefaultContractResolver

    protected override List<MemberInfo> GetSerializableMembers(Type objectType)
    
        return base.GetSerializableMembers(objectType).Where(member => member.DeclaringType == typeof(ParentClass) || typeof(ParentClass).IsSubclassOf(member.DeclaringType)).ToList();
    

但是当我以下列方式使用它时:

var instance = new ChildClass()

    Item1 = "abc",
    Item2 = new CustomModel()
    
        CustomItem1 = "def",
        CustomItem2 = "ghi"
    ,
    Item3 = "jkl",
    Item4 = "mno",
;

var settings = new JsonSerializerSettings

    ContractResolver = new CustomResolver(),
;
var json = JsonConvert.SerializeObject(instance, Formatting.Indented, settings);
Console.WriteLine(json);        

打印以下 JSON:


  "Item1": "abc",
  "Item2":  

演示here.

如果我不使用合约解析器,则会打印以下 JSON:


  "Item3": "jkl",
  "Item4": "mno",
  "Item1": "abc",
  "Item2": 
    "CustomItem1": "def",
    "CustomItem2": "ghi"
  

演示小提琴#2 here.

谁能解释一下这个问题?

【问题讨论】:

修复编译错误后无法reproduce。 minimal reproducible example 这里:dotnetfiddle.net/nMs9Hb。在此处修复:dotnetfiddle.net/nMs9Hb。由于一些可怜的谷歌验证码,我似乎无法发布答案。您的问题有些问题,因为您为 编写的代码但是当我以下列方式使用它时: 实际上并没有显示正在使用的合同解析器。 请检查我对您问题的编辑,看看它是否正确。我认为我已经证明了这个问题,但请确保。 @GuruStron 您无法重现它的原因是因为您没有使用自定义解析器。 @RyanFalzon 是的,没有仔细研究复制的代码) 【参考方案1】:

您的CustomResolver 可能会修复如下:

public class CustomResolver : DefaultContractResolver

    protected override List<MemberInfo> GetSerializableMembers(Type objectType)
    
        var members = base.GetSerializableMembers(objectType);
        if (objectType.IsSubclassOf(typeof(ParentClass)))
            members = members.Where(m => m.DeclaringType == typeof(ParentClass)).ToList();
        return members;
    

您的问题是 CustomModel 不是 ParentClass 的子类,因此它的属性根本不应该被过滤掉——但它们被过滤掉了,而且都被过滤掉了,因为它们不是由 ParentClass 声明的。

(我不确定您对 typeof(ParentClass).IsSubclassOf(member.DeclaringType) 的用途。ParentClass 的唯一基类是 object,它没有任何属性。)

演示小提琴here.

【讨论】:

宾果游戏!这解决了我的问题。非常感谢。

以上是关于Json.Net 自定义 ContractResolver 忽略自定义对象的主要内容,如果未能解决你的问题,请参考以下文章

如何在 JSON.NET 中实现自定义 JsonConverter?

使用 Json.NET 自定义反序列化

ASP.NET MVC 下自定义 JsonResult,使用 Json.NET 序列化 JSON

具有数据类型的 Json.NET 自定义 JsonConverter

如何在 ASP.NET Web API 中为 Json.NET 设置自定义 JsonSerializerSettings?

使用 JSON.NET 反序列化自定义 null 处理