JSON.NET StackOverflowException 和 [JsonConvert]
屬性
將 [JsonConvert]
屬性應用於自訂 JsonConverter
可能會在序列化期間導致 StackOverflowException
,特別是對於複雜物件。這通常是由於 JSON.NET 內部序列化過程中的無限遞歸所造成的。雖然直接將 JsonConvert.SerializeObject()
與自訂轉換器一起使用是推薦的解決方案,但本節探討了需要該屬性時的替代方法。
1。完善WriteJson
方法
問題的核心通常在於自訂轉換器的 WriteJson
方法。 對邊緣情況處理不充分可能會觸發無限循環。 以下改進的 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
傳回 false 的屬性。 它還可以正確地將序列化委託給屬性的轉換器(如果存在並且可以寫入),否則直接使用序列化器。
2。具有堆疊大小限制的遞歸呼叫
或者,您可以在 WriteJson
方法中加入堆疊深度檢查以防止失控遞歸:
<code class="language-csharp">public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { const int MaxStackSize = 65536; // Adjust as needed if (writer.CurrentDepth > MaxStackSize) { throw new JsonSerializationException("Stack overflow detected during serialization."); } // Your custom serialization logic here... }</code>
如果遞歸深度超過預先定義的限制,此方法會引發描述性異常,從而防止 StackOverflowException
。 根據您的物件複雜度調整 MaxStackSize
。
結論
雖然 [JsonConvert]
屬性提供了便利,但將其與自訂轉換器一起使用需要仔細考慮。 透過增強 WriteJson
方法來處理邊緣情況和/或合併堆疊大小檢查,您可以有效降低序列化期間 StackOverflowException
的風險。 請記住,手動呼叫 JsonConvert.SerializeObject()
仍然是最安全、最可靠的方法。
以上是為什麼將「[JsonConvert()]」註解與自訂 JsonConverters 一起使用有時會導致 StackOverflowException,如何防止它?的詳細內容。更多資訊請關注PHP中文網其他相關文章!