【问题标题】:json.net serializing only selected nested propertiesjson.net 仅序列化选定的嵌套属性
【发布时间】:2022-01-25 19:42:50
【问题描述】:

我想使用 json.net 和 C# 序列化对象。另外,我只希望选定的属性位于返回的最终 JSON 对象中。我有两节课

public class EmployeeClass {
 
   [JsonProperty("className")]
   public string Name{ get; set;}
   
   [JsonProperty("hierUnitId")]
   public int? HierUnitId { get; set; }
   
   [JsonProperty("rvcOperatorOptions")]
   public List<OperatorOptions> RvcOperatorOptions{get; set;}
 
}

public class OperatorOptions{

     [JsonProperty("rvcObjNum")]
     public int? RvcObjectNum {get; set;}

     [JsonProperty("options")]
     public string Options {get; set;}

 }    

现在我有一个 EmployeeClass 对象,我想serialize

{   
   "className" : "EmpClass",
   "hierUnitId" : 101,
   "rvcOperatorOptions" : [
            { "rvcObjNum" : 10 , "options" : "00010011" } ,
            { "rvcObjNum" : 11 , "options" : "11110011" }
    ]

}

为此,我重写了 DefaultContractResolver 类的 CreateProperties 方法,只包含选定的属性。此外,我将要包含的属性列表传递给我的 CustomRetrieveResponseResolver 扩展 @ 类的构造函数987654328@.

private readonly IList<string> _propertiesToInclude;
public CustomRetrieveResponseResolver(IList<string> propertiesToInclude)
{
    _propertiesToInclude = propertiesToInclude;
}

我有一个字符串列表propertiesToInclude,其中包含要包含的属性名称。

例如:
propertiesToInclude = { "Name" , "RvcOperatorOptions.RvcObjectNum" }

现在的问题是,在propertiesToInclude 列表中,我有嵌套属性的相对名称。我知道CreateProperties 将被调用两次,一次为EmployeeClass,然后为OperatorOptions Class(由于 EmployeeClass 中的List&lt;OperatorOptions&gt; RvcOperatorOptions)。有没有办法以这种方式进行序列化?就像上述对象的输出将是

{   
       "className" : "EmpClass",
       "rvcOperatorOptions" : [
                { "rvcObjNum" : 10 } ,
                { "rvcObjNum" : 11  }
        ]
    
}    

有人可以帮我解决这个问题,即使用嵌套属性的使用路径序列化选定的值吗?

【问题讨论】:

  • Json.NET 是一个基于契约的序列化器。它为一个类型定义一个契约,然后根据契约进行序列化。因此,没有(直接的)方法可以在序列化图中的不同位置为 same type 使用不同的合约。有关讨论和解决方法,请参阅:How to perform partial object serialization providing "paths" using Newtonsoft JSON.NET。事实上,这可能是重复的,同意吗?
  • 话虽如此,在您的示例中,您实际上并不需要按路径过滤属性,对吗?通过IList&lt;Type, IList&lt;string&gt;&gt; propertiesByTypeToInclude 过滤应该已经足够了,不是吗?

标签: c# asp.net serialization json.net resolver


【解决方案1】:

如果您想在序列化/重新序列化时忽略属性,请使用[JsonIgnore] 属性。

对于属性的动态排除:

public class CustomPropertiesContractResolver : DefaultContractResolver
{
    private HashSet<string> _propertySet;
    
    public CustomPropertiesContractResolver(IEnumerable<string> propertyNames)
    {
        if (propertyNames != null)
        {
            _propertySet = new HashSet<string>(propertyNames, StringComparer.OrdinalIgnoreCase);
        }
    }
    
    protected override List<MemberInfo> GetSerializableMembers(Type objectType)
    {
        List<MemberInfo> serializableMembers = null;
        var allMembers = base.GetSerializableMembers(objectType);
   
        if (_propertySet != null && _propertySet.Count > 0)
        {
            serializableMembers = allMembers.Where(m => !_propertySet.Contains(m.Name)).ToList();
        }
        return serializableMembers != null && serializableMembers.Count > 0 ? serializableMembers : allMembers;
    }
}

用法

var serializedStr = JsonConvert.SerializeObject(employeeObj, new JsonSerializerSettings()
{
    ContractResolver = new CustomPropertiesContractResolver(new List<string>{"options"})
};);
     

要提供深度并能够跟踪嵌套属性的合同,请查看以下答案:Json.NET serialize by depth and attribute

【讨论】:

  • 这不起作用,因为我必须动态忽略属性。我必须包含 listpropertiesToInclude 中的属性。
  • 我正在更新我的答案。看看,让我知道。
  • 这将起作用,但不适用于我给出的示例中的嵌套属性。就像“RvcOperatorOptions.RvcObjNum”一样,您的解决方案将不起作用。
  • 我更新了答案,创建了一个自定义 ContractResolver 并覆盖了 GetSerializableMembers。我还没有完全测试它,但你可以试一试。如果它不起作用,我将创建一个解决方案并在此基础上工作。
  • 同样的事情这也不起作用,因为我使用了 CreateProperties,它也在内部调用 GetSerializableMembers,所以它是相同的事情。这也不适用于嵌套的。
猜你喜欢
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
  • 2013-09-02
  • 2014-02-19
  • 2011-09-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多