使用Newtonsoft,我们有一个用于忽略空集合的自定义解析器。对于新的system.text.json在.Net内核3.1中是否有任何等效的配置?
发布于 2021-04-09 13:50:45
来自.NET 5公司2020年官方如何从Newtonsoft.Json迁移到System.Text.Json的如何从Newtonsoft.Json迁移到System.Text.Json12月14日称:
System.Text.Json提供了在序列化时忽略属性或字段的下列方法:
这些选项不允许你:
对于该功能,您可以编写自定义转换器。下面是一个POCO示例和一个自定义转换器,说明了这种方法:
(以下类型的自定义转换器示例)
请注意,此转换器需要是包含集合属性的类型的转换器,而不是集合类型的转换器(请参阅我的第二个答案)。
发布于 2022-09-19 18:33:50
TypeInfoResolver
添加了.NET 7(在较旧的运行时通过system.text.json nuget包访问,在此答案发布前)允许这样做。
示例:
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;
}
}
}
}
产出:
{"Ints":[3,4,5]}
发布于 2021-04-09 14:44:06
一次尝试
我知道这不是你想要的,但也许有人可以在此基础上发展,或者有一个非常渺茫的机会,它可能适合某些情况。
我所做的
的对象new A()
public class A
{
public List<int> NullList {get;set;}
public List<int> EmptyList {get;set;} = new List<int>();
};
变成了
{
"EmptyList": null
}
文档
自2021年2月25日起,自定义转换器模式中的如何在.NET中为JSON序列化(编组)编写自定义转换器表示:
创建自定义转换器有两种模式:基本模式和工厂模式。工厂模式用于处理Enum类型或开放泛型的转换器。基本模式适用于非泛型和封闭泛型类型.例如,下列类型的转换器需要工厂模式:
基本模式可以处理的类型的一些示例包括:
基本模式创建一个可以处理一种类型的类。工厂模式创建一个类,在运行时确定需要哪种特定类型,并动态地创建适当的转换器。
我所做的
演示
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);
}
}
}
转换器
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);
}
}
}
}
https://stackoverflow.com/questions/59720612
复制相似问题