我正在尝试将 json 反序列化为具有
Dictionary<string,string>
类型属性的对象。我将词典的比较器指定为 StringComparer.OrdinalIgnoreCase
。
这是这门课:
class DictionaryTest
{
public Dictionary<string, string> Fields { get; set; }
public DictionaryTest()
{
Fields = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
}
但是当反序列化发生时,比较器将更改为通用比较器。因此,我无法以不区分大小写的方式访问字典的键。
var points = new Dictionary<string, string>
{
{ "James", "9001" },
{ "Jo", "3474" },
{ "Jess", "11926" }
};
var testObj = new DictionaryTest{Fields = points};
var dictionaryJsonText = JsonSerializer.Deserialize<DictionaryTest>(JsonSerializer.Serialize(testObj, options:new JsonSerializerOptions()
{
IgnoreNullValues = true,
WriteIndented = false,
PropertyNamingPolicy = null,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
PropertyNameCaseInsensitive = true
}));
string nameJsonText = "", nameJsonText2="";
//Because of the naming policy specified above, the keys are camelCase.
//So keys are james, jo and jess
//I expect to be able to access either james, or James as keys.
dictionaryJsonText?.Fields.TryGetValue("James", out nameJsonText);
dictionaryJsonText?.Fields.TryGetValue("james", out nameJsonText2);
Console.WriteLine($"Name with system.text.json is: {nameJsonText}");
Console.WriteLine($"Name with system.text.json is: {nameJsonText2}");
Console.WriteLine($"Comparer is {dictionaryJsonText?.Fields.Comparer}");
那么我该如何将 json 反序列化为如下所示的类并保持其不区分大小写呢?有什么建议么?我正在使用.net5。 我应该提到的是,使用
Newtonsoft
这段代码可以完美地工作。比较器将保留为 OrdinalIgnoreCase 并保留不区分大小写。
目前没有办法做你想做的事。但是,您可以自己实现该功能。
您可以为此特定案例创建自定义
JsonConverter
。例如:
public sealed class CaseInsensitiveDictionaryConverter<TValue>
: JsonConverter<Dictionary<string, TValue>>
{
public override Dictionary<string, TValue> Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options)
{
var dic = (Dictionary<string, TValue>)JsonSerializer
.Deserialize(ref reader, typeToConvert, options);
return new Dictionary<string, TValue>(
dic, StringComparer.OrdinalIgnoreCase);
}
public override void Write(
Utf8JsonWriter writer,
Dictionary<string, TValue> value,
JsonSerializerOptions options)
{
JsonSerializer.Serialize(
writer, value, value.GetType(), options);
}
}
然后您可以通过执行以下操作将其绑定到特定属性:
class DictionaryTest
{
[JsonConverter(typeof(CaseInsensitiveDictionaryConverter<string>))]
public Dictionary<string, string> Fields { get; set; }
= new Dictionary<string, string>();
}
就是这样。您可以像平常一样反序列化:
var json = JsonSerializer.Serialize(new DictionaryTest
{
Fields =
{
{ "One", "Two" },
{ "Three", "Four" }
}
});
var dictionaryJsonText = JsonSerializer.Deserialize<DictionaryTest>(json);
上面的示例将生成一个不区分大小写键的字典。
这个问题很老了,但我想说我有更好的解决方案。下面的解决方案不会创建额外的字典,因此内存流量较低。
JsonSerializerOptions JsonSerializerOptions =
new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
PropertyNameCaseInsensitive = false,
TypeInfoResolver = new DefaultJsonTypeInfoResolver()
};
string valuesAsJson =
"""
{
"key1": "value1",
"key2": "value2",
"key3": "value3",
"Key1": "value3"
}
""";
JsonTypeInfo<Dictionary<string, string?>> jsonTypeInfo =
JsonTypeInfo.CreateJsonTypeInfo<Dictionary<string, string?>>(
JsonSerializerOptions
);
jsonTypeInfo.CreateObject = () => new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase);
Dictionary<string, string?>? values =
JsonSerializer.Deserialize<Dictionary<string, string?>>(
valuesAsJson,
jsonTypeInfo
);
似乎有一个选项可以实现这一目标。
JsonSerializerOptions options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
await JsonSerializer.DeserializeAsync<...>(stream, options)