C# System.Text.Json将字典序列化为数组

C# System.Text.Json将字典序列化为数组,c#,.net-core,system.text.json,C#,.net Core,System.text.json,是否可以使用System.Text.Json将字典序列化(和反序列化)为数组 我需要将字典序列化为{“hello”:“world”}而不是{“key”:“hello”,“value”:“world”},最好不必设置类的dictionary属性 使用newtonsoft.json,可以通过以下方式实现: class DictionaryAsArrayResolver : DefaultContractResolver { protected override JsonContract Cr

是否可以使用System.Text.Json将字典序列化(和反序列化)为数组

我需要将字典序列化为
{“hello”:“world”}
而不是
{“key”:“hello”,“value”:“world”}
,最好不必设置类的dictionary属性

使用newtonsoft.json,可以通过以下方式实现:

class DictionaryAsArrayResolver : DefaultContractResolver
{
    protected override JsonContract CreateContract(Type objectType)
    {
        if (objectType.GetInterfaces().Any(i => i == typeof(IDictionary) || 
           (i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDictionary<,>))))
        {
            return base.CreateArrayContract(objectType);
        }

        return base.CreateContract(objectType);
    }
}
类字典ArrayResolver:DefaultContractResolver
{
受保护的重写JsonContract CreateContract(类型objectType)
{
if(objectType.GetInterfaces().Any(i=>i==typeof(IDictionary)|
(i.IsGenericType&&i.GetGenericTypeDefinition()==typeof(IDictionary)))
{
返回base.CreateArrayContract(objectType);
}
返回base.CreateContract(objectType);
}
}
您可以使用为要序列化为数组的每种字典类型制作特定的。这里有一个这样的转换器,它适用于实现
IDictionary
的每个类:

或在ASP.NET Core中全局显示,如所示:

如果您只想将某些字典类型序列化为数组,则也可以直接使用底层的单个转换器
DictionaryArrayConverter

注:

  • JsonSerializer
    当前在序列化
    KeyValuePair
    时不尊重(请参阅),因此我必须引入
    KeyValueDTO
    ,以获得您问题中所需的大小写
    “key”
    “value”

  • 我没有为非泛型
    IDictionary
    类型实现转换器。这可以作为答案的延伸

  • 有关转换器工厂模式的更多信息,请参阅

  • System.Text.Json
    中的
    DefaultContractResolver
    等效的类型是内部的。有一个公开的增强要求一个公共等价物


demo小提琴。

如果你想保持它的简短和简单,你可以考虑匿名类型的投影:

var dictionary = new Dictionary<string, string>();
dictionary.Add("hello", "world");
dictionary.Add("how", "are you?");

var o = JsonSerializer.Serialize(dictionary.Select(x => new { key = x.Key, value = x.Value }));
// [{"key":"hello","value":"world"},{"key":"how","value":"are you?"}]

我认为调用
Dictionary.ToList()
可能更快更简单,但我喜欢您提供的深度定制demonstrate@JoshE-当dictionary是根对象时,返回列表是有意义的,但是OP的问题表明它是我的类的属性,并且暗示OP不想修改模型。在这种情况下,转炉厂是合适的。此外,如注释中所述,
JsonSerializer
目前不尊重
KeyValuePair
PropertyNamingPolicy
,因此意味着返回
ToList()
将导致不正确的大小写。在这两个方面,我从OP询问问题的方式中推断了太多
var options = new JsonSerializerOptions
{
    Converters = { new DictionaryConverterFactory() },
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};

var json = JsonSerializer.Serialize(dictionary, options);

var dictionary2 = JsonSerializer.Deserialize<TDictionary>(json, options);
services.AddControllers().AddJsonOptions(options =>
{
    options.JsonSerializerOptions.Converters.Add(new DictionaryConverterFactory());
    options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});
var dictionary = new Dictionary<string, string>();
dictionary.Add("hello", "world");
dictionary.Add("how", "are you?");

var o = JsonSerializer.Serialize(dictionary.Select(x => new { key = x.Key, value = x.Value }));
// [{"key":"hello","value":"world"},{"key":"how","value":"are you?"}]
JsonSerializer.Serialize(dictionary.ToList());
// [{"Key":"hello","Value":"world"},{"Key":"how","Value":"are you?"}]