gpt4 book ai didi

c# - NullValueHandling.Ignore 影响反序列化到 [ExtensionData] 尽管匹配类成员

转载 作者:行者123 更新时间:2023-11-30 14:51:14 25 4
gpt4 key购买 nike

我的服务器响应由一组已知和未知属性组成。对于已知的,我创建了一个 DTO 类,其中包含每个属性的成员。未知属性应放在用 [ExtensionData] 属性注释的字典中:

[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class Dto
{

[JsonExtensionData]
private readonly Dictionary<string, object> unknownProperties = new Dictionary<string, object>();

public IDictionary<string, object> UnknownProperties
{
get
{
return new ReadOnlyDictionary<string, object>(this.unknownProperties);
}
}

[JsonProperty(Required = Required.Default, PropertyName = "KNOWN_PROPERTY")]
public string KnownProperty { get; private set; }
}

Null 可以作为 KnownProperty 的值。如果我尝试反序列化包含 KNOWN_PROPERTY : null 的 JSON 对象,则此属性也包含在字典 UnknownProperties 中,如果我使用 NullValueHandling.Ignore 配置序列化程序。即使存在 KNOWN_PROPERTY 的类成员,也会这样做:

static void Main(string[] args)
{
string jsonString = @"{
KNOWN_PROPERTY : null,
UNKNOWN_PROPERTY : null
}";

JsonSerializer serializer = JsonSerializer.CreateDefault(new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore
});

using (var textReader = new StringReader(jsonString))
{
Dto dto = serializer.Deserialize<Dto>(new JsonTextReader(textReader));
foreach (var pair in dto.UnknownProperties)
{
Console.WriteLine("{0}: {1}", pair.Key, pair.Value == null ? "null" : pair.Value.ToString());
}
}
}

输出:

 KNOWN_PROPERTY : null
UNKNOWN_PROPERTY : null

如果我使用 NullValueHandling.Include 配置序列化程序或在 JSON 字符串中为 KNOWN_PROPERTY 设置值,则字典仅包含 UNKNOWN_PROPERTY,正如预期的那样。

据我了解,如果 NullValueHandling 设置为忽略,[ExtensionData] 将无法正常工作,因为 documentation声明只有在找不到匹配的类成员时才使用扩展。

我看到的行为是故意的吗?我可以做些什么来避免这种情况吗?因为我不喜欢向服务器发送空值,所以我想坚持使用当前设置的 NullValueHandling

我正在使用 Json.NET 8.0.2

最佳答案

更新

报告于 JsonExtensionData should not include the null values that are real object properties. #1719并在提交中修复 e079301 .该修复程序应包含在 11.0.2 之后的下一个 Json.NET 版本中。

原始答案

确认 - 在 JsonSerializerInternalReader.PopulateObject(object, JsonReader, JsonObjectContract, JsonProperty, string)有以下逻辑:

// set extension data if property is ignored or readonly
if (!SetPropertyValue(property, propertyConverter, contract, member, reader, newObject))
{
SetExtensionData(contract, member, reader, memberName, newObject);
}

如果要忽略属性,其意图似乎是将值放入扩展数据中,但如果,Json.NET 将其放入扩展数据中> 被忽略——一个稍微不同的概念。我同意这可能是一个错误。你可能想要 report it .

有一个解决方法。 Json.NET 有两个属性会影响空值/默认值的序列化方式:

  • NullValueHandling .指定在序列化和反序列化对象时包含或忽略空值。值为 IncludeIgnore

  • DefaultValueHandling .这有更复杂的语义:

    1. Include:在序列化对象时包含成员值与成员默认值相同的成员。包含的成员被写入 JSON。反序列化时无效。
    2. Ignore:在序列化对象时忽略成员值与成员默认值相同的成员,这样就不会写入 JSON。此选项将忽略所有默认值(例如,对象和可空类型为 null;整数、小数和 float 为 0; bool 值为 false)。
    3. Populate:具有默认值但没有 JSON 的成员在反序列化时将设置为其默认值。
    4. IgnoreAndPopulate:在序列化对象时忽略成员值与成员默认值相同的成员,并在反序列化时将成员设置为默认值。

那么,这些重叠的设置如何相互作用?事实证明,Json.NET 会同时检查它们:如果两个设置都同意则序列化,如果两个设置都同意则反序列化。并且 DefaultValueHandling.IgnoreAndPopulate 似乎做你想做的事——它在序列化时省略空值,但在反序列化时读取并设置它们(如果存在)。

因此我能够通过以下 JsonProperty 获得您想要的行为:

public class Dto
{
[JsonProperty(Required = Required.Default, PropertyName = "KNOWN_PROPERTY", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate, NullValueHandling = NullValueHandling.Include)]
public string KnownProperty { get; private set; }

// Remainder as before.
}

原型(prototype) fiddle .

关于c# - NullValueHandling.Ignore 影响反序列化到 [ExtensionData] 尽管匹配类成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34995406/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com