11

Newtonsoft を使用して、空のコレクションを無視するためのカスタム リゾルバーを作成しました。.Netコア3.1の新しいsystem.text.jsonに相当する構成はありますか

4

2 に答える 2

0

試み

これはあなたが求めているものではないことはわかっていますが、誰かがこれに基づいて構築できるか、いくつかのシナリオに適合する可能性が非常にわずかです。

できたこと

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 シリアル化 (マーシャリング) 用のカスタム コンバーターを作成する方法 には、次のように書かれています

カスタム コンバーターの作成には、基本パターンとファクトリー パターンの 2 つのパターンがあります。ファクトリ パターンは、列挙型またはオープン ジェネリックを処理するコンバーター用です。基本的なパターンは、非ジェネリックおよびクローズ ジェネリック型用です。たとえば、次の型のコンバーターにはファクトリ パターンが必要です。

  • Dictionary<TKey,TValue>
  • 列挙型
  • リスト

基本パターンで処理できる型の例としては、次のようなものがあります。

  • Dictionary<int, string>
  • WeekdaysEnum
  • リスト
  • 日付時刻
  • Int32

基本パターンは、1 つの型を処理できるクラスを作成します。ファクトリ パターンは、実行時に必要な特定の型を決定し、適切なコンバーターを動的に作成するクラスを作成します。

私がしたこと

デモ

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://docs.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);
            }
        }
    }
}
于 2021-04-09T14:44:06.380 に答える