首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C# .Net Core 3.1 System.Text.Json忽略序列化中的空集合

C# .Net Core 3.1 System.Text.Json忽略序列化中的空集合
EN

Stack Overflow用户
提问于 2020-01-13 16:37:26
回答 3查看 4.4K关注 0票数 12

使用Newtonsoft,我们有一个用于忽略空集合的自定义解析器。对于新的system.text.json在.Net内核3.1中是否有任何等效的配置?

EN

回答 3

Stack Overflow用户

发布于 2021-04-09 13:50:45

来自.NET 5公司2020年官方如何从Newtonsoft.Json迁移到System.Text.Json如何从Newtonsoft.Json迁移到System.Text.Json12月14日称:

System.Text.Json提供了在序列化时忽略属性或字段的下列方法:

  • JsonIgnore属性(.)
  • IgnoreReadOnlyProperties全局选项(.)
  • (...)JsonSerializerOptions.IgnoreReadOnlyFields全局(.)
  • DefaultIgnoreCondition全局选项允许您忽略所有具有默认值的值类型属性,或者忽略所有具有空值的引用类型属性。

这些选项不允许你:

  • 忽略基于运行时计算的任意标准的选定属性。

对于该功能,您可以编写自定义转换器。下面是一个POCO示例和一个自定义转换器,说明了这种方法:

(以下类型的自定义转换器示例)

请注意,此转换器需要是包含集合属性的类型的转换器,而不是集合类型的转换器(请参阅我的第二个答案)。

票数 2
EN

Stack Overflow用户

发布于 2022-09-19 18:33:50

TypeInfoResolver添加了.NET 7(在较旧的运行时通过system.text.json nuget包访问,在此答案发布前)允许这样做。

示例:

代码语言:javascript
运行
复制
using System.Collections;
using System.Text.Json;
using System.Text.Json.Serialization.Metadata;

public class TestObject {
    public List<int> Ints { get; } = new() {3, 4, 5};
    public List<int> EmptyInts { get; } = new();
    public List<int> NullInts { get; }
}

public static class Program {
    public static void Main() {
        var options = new JsonSerializerOptions {
            TypeInfoResolver = new DefaultJsonTypeInfoResolver {
                Modifiers = {DefaultValueModifier}
            },
        };
        var obj = new TestObject();
        var text = JsonSerializer.Serialize(obj, options);
        Console.WriteLine(text);
    }

    private static void DefaultValueModifier(JsonTypeInfo type_info) {
        foreach (var property in type_info.Properties) {
            if (typeof(ICollection).IsAssignableFrom(property.PropertyType)) {
                property.ShouldSerialize = (_, val) => val is ICollection collection && collection.Count > 0;
            }
        }
    }
}

产出:

代码语言:javascript
运行
复制
{"Ints":[3,4,5]}
票数 2
EN

Stack Overflow用户

发布于 2021-04-09 14:44:06

一次尝试

我知道这不是你想要的,但也许有人可以在此基础上发展,或者有一个非常渺茫的机会,它可能适合某些情况。

我所做的

的对象new A()

代码语言:javascript
运行
复制
public class A
{
   public List<int> NullList {get;set;}
   public List<int> EmptyList {get;set;} = new List<int>();
};

变成了

代码语言:javascript
运行
复制
{
  "EmptyList": null
}

文档

自2021年2月25日起,自定义转换器模式中的如何在.NET中为JSON序列化(编组)编写自定义转换器表示:

创建自定义转换器有两种模式:基本模式和工厂模式。工厂模式用于处理Enum类型或开放泛型的转换器。基本模式适用于非泛型和封闭泛型类型.例如,下列类型的转换器需要工厂模式:

  • Dictionary
  • 枚举
  • 列表

基本模式可以处理的类型的一些示例包括:

  • Dictionary
  • WeekdaysEnum
  • 列表
  • DateTime
  • Int32

基本模式创建一个可以处理一种类型的类。工厂模式创建一个类,在运行时确定需要哪种特定类型,并动态地创建适当的转换器。

我所做的

演示

代码语言:javascript
运行
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;

#nullable disable

namespace Sandbox4
{
 
    public class A
    {
        public List<int> NullList {get;set;}
        public List<int> EmptyList {get;set;} = new List<int>();
     };

    public class Program
    {
        public static void Main()
        {
            A a = new ();

            JsonSerializerOptions options = new ()
            {
                DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingDefault,
                WriteIndented = true,
                Converters =
                {  
                     new IEnumerableTConverter()
                }
            };

            string aJson =
                JsonSerializer.Serialize<A>(a, options);
            
            Console.WriteLine(aJson);
        }
    }
}

转换器

代码语言:javascript
运行
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Sandbox4
{
    // Modified DictionaryTEnumTValueConverter 
    // from https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to?pivots=dotnet-5-0#custom-converter-patterns
    public class IEnumerableTConverter : JsonConverterFactory
    {
        public override bool CanConvert(Type typeToConvert)
        {
            if (!typeToConvert.IsGenericType)
            {
                return false;
            }

            var realType = typeToConvert.GetGenericTypeDefinition();
            if (realType.IsAssignableTo(typeof(IEnumerable<>)))
            {
                return false;
            }
            return true;
        }

        public override JsonConverter CreateConverter(
            Type type,
            JsonSerializerOptions options)
        {
            Type generictype = type.GetGenericArguments()[0];

            JsonConverter converter = (JsonConverter)Activator.CreateInstance(
                typeof(ICollectionTConverterInner<,>).MakeGenericType(
                    new Type[] { type, generictype }),
                BindingFlags.Instance | BindingFlags.Public,
                binder: null,
                args: new object[] { type, options },
                culture: null);

            return converter;
        }

        private class ICollectionTConverterInner<T,U> :
            JsonConverter<T> where T: IEnumerable<U>
        {
            private readonly JsonConverter<T> _normalConverter;

            public ICollectionTConverterInner(Type type,JsonSerializerOptions options)
            {
                // For performance, use the existing converter if available.
                var existing = new JsonSerializerOptions().GetConverter(type);
                if( existing == null ) throw new ApplicationException($"Standard converter for {type} not found.");

                _normalConverter = (JsonConverter<T>) existing;
            }

            public override T Read(
                ref Utf8JsonReader reader,
                Type typeToConvert,
                JsonSerializerOptions options)
            {
                // Untested
                return _normalConverter.Read(ref reader, typeToConvert, options);
            }

            public override void Write(
                Utf8JsonWriter writer,
                T collection,
                JsonSerializerOptions options)
            {
                if(!collection.Any()) 
                {
                    writer.WriteNullValue();
                    return;
                }

                _normalConverter.Write(writer, collection, options);
            }
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59720612

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档