问题:
使用 JSON.Net 中的 [JsonConvert] 属性将复杂的对象序列化为扁平化的 JSON 可以触发 StackOverflowException
.
根本原因:
提供的FJson
自定义转换器采用递归方法(WriteJson
)将对象图写入JSON编写器。这种递归方法缺乏针对各种场景的足够保护措施,导致潜在的无限循环和堆栈溢出错误。 这些场景包括:
ShouldSerialize*()
方法:确定属性序列化的自定义方法可能会导致意外递归。解决方案:
解决这个StackOverflowException
的关键在于增强WriteJson
转换器的FJson
方法来解决这些边缘情况。 修改后的WriteJson
方法如下所示:
<code class="language-csharp">public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (ReferenceEquals(value, null)) { writer.WriteNull(); return; } var contract = (JsonObjectContract)serializer .ContractResolver .ResolveContract(value.GetType()); writer.WriteStartObject(); foreach (var property in contract.Properties) { if (property.Ignored) continue; if (!ShouldSerialize(property, value)) continue; var propertyName = property.PropertyName; var propertyValue = property.ValueProvider.GetValue(value); writer.WritePropertyName(propertyName); if (property.Converter != null && property.Converter.CanWrite) { property.Converter.WriteJson(writer, propertyValue, serializer); } else { serializer.Serialize(writer, propertyValue); } } writer.WriteEndObject(); } private static bool ShouldSerialize(JsonProperty property, object instance) { return property.ShouldSerialize == null || property.ShouldSerialize(instance); }</code>
此改进版本显式处理空值,并合并 ShouldSerialize
辅助方法来有效管理自定义 ShouldSerialize*()
方法,从而防止导致 StackOverflowException
的无限递归。 它还在适当的情况下正确地将序列化委托给现有转换器。 这种修改后的方法应该可靠地序列化复杂对象,而在与 [JsonConvert] 属性一起使用时不会遇到堆栈溢出错误。
以上是为什么我的 JsonConvert 属性在序列化复杂对象时会导致 StackOverflowException?的详细内容。更多信息请关注PHP中文网其他相关文章!