System.Text.Json API 有类似 IContractResolver 的东西

Posted

技术标签:

【中文标题】System.Text.Json API 有类似 IContractResolver 的东西【英文标题】:System.Text.Json API is there something like IContractResolver 【发布时间】:2020-03-14 12:06:19 【问题描述】:

在新的 System.Text.Json 中;命名空间是否有类似 IContractResolver 的东西我正在尝试将我的项目从 Newtonsoft 迁移出来。

这是我要迁移的课程之一:

public class SelectiveSerializer : DefaultContractResolver

private readonly string[] fields;

public SelectiveSerializer(string fields)

  var fieldColl = fields.Split(',');
  this.fields = fieldColl
      .Select(f => f.ToLower().Trim())
      .ToArray();


protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)

  var property = base.CreateProperty(member, memberSerialization);
  property.ShouldSerialize = o => fields.Contains(member.Name.ToLower());

  return property;


【问题讨论】:

你用过.net core 3.0吗?能分享一下为什么要从Newtonsoft迁移到System.Text.Json吗?其实net core 3.0可以支持Newtonsoft。你的代码是怎么做的工作吗?是用来小写正文数据的吗? @Rena 此代码用于构建我们自己的 api 选择函数。例如: select=FirstName,Email,Id 序列化程序只会序列化指定的字段。类似于 odata 的做法,因为我们正在远离 odata System.Text.Json 中的等效类型 -- JsonClassInfoJsonPropertyInfo -- 是 internal。有一个开放的增强功能Equivalent of DefaultContractResolver in System.Text.Json #42001 要求公开等效。 @dbc 很高兴知道:) 【参考方案1】:

System.Text.Json 中的等效类型——JsonClassInfoJsonPropertyInfo——是internal。有一个开放的增强 Equivalent of DefaultContractResolver in System.Text.Json #31257 要求公共等价物。 – dbc 11 月 25 日 19:11

Github 问题:

Open up metadata infrastructure of System.Text.Json #34456 Equivalent of DefaultContractResolver.CreateProperties override in System.Text.Json #60518 Equivalent of DefaultContractResolver in System.Text.Json #31257

请试试这个: 我把它写成 System.Text.Json 的扩展来提供缺失的功能:https://github.com/dahomey-technologies/Dahomey.Json。

您会发现对编程对象映射的支持。

定义您自己的 IObjectMappingConvention 实现:

public class SelectiveSerializer : IObjectMappingConvention

    private readonly IObjectMappingConvention defaultObjectMappingConvention = new DefaultObjectMappingConvention();
    private readonly string[] fields;

    public SelectiveSerializer(string fields)
    
        var fieldColl = fields.Split(',');
        this.fields = fieldColl
            .Select(f => f.ToLower().Trim())
            .ToArray();
    

    public void Apply<T>(JsonSerializerOptions options, ObjectMapping<T> objectMapping) where T : class
    
        defaultObjectMappingConvention.Apply<T>(options, objectMapping);
        foreach (IMemberMapping memberMapping in objectMapping.MemberMappings)
        
            if (memberMapping is MemberMapping<T> member)
            
                member.SetShouldSerializeMethod(o => fields.Contains(member.MemberName.ToLower()));
            
        
    

定义你的类:

public class Employee

    public int Id  get; set; 
    public string FirstName  get; set; 
    public string LastName  get; set; 
    public string Email  get; set; 

通过调用命名空间 Dahomey.Json 中定义的扩展方法 SetupExtensions 的 JsonSerializerOptions 来设置 json 扩展:

JsonSerializerOptions options = new JsonSerializerOptions();
options.SetupExtensions();

为类注册新的对象映射约定:

options.GetObjectMappingConventionRegistry().RegisterConvention(
    typeof(Employee), new SelectiveSerializer("FirstName,Email,Id"));

然后使用常规的 Sytem.Text.Json API 序列化您的类:

Employee employee = new Employee

    Id = 12,
    FirstName = "John",
    LastName = "Doe",
    Email = "john.doe@acme.com"
;
        
string json = JsonSerializer.Serialize(employee, options);
// "Id":12,"FirstName":"John","Email":"john.doe@acme.com";

【讨论】:

以上是关于System.Text.Json API 有类似 IContractResolver 的东西的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 System.Text.Json API 将流反序列化为对象

是否可以在 System.Text.Json 中找到未映射的属性?

System.Text.Json 中的 JsonExtensionData

为啥使用 System.Text.Json 的 JSON 反序列化这么慢?

System.Text.Json:如何为枚举值指定自定义名称?

使用System.Text.Json(.netcore-3.0)代替Newtonsoft.Json的扩展功能是什么?