JSON.NET StackOverflowException dan [JsonConvert]
Atribut
Menggunakan atribut [JsonConvert]
pada tersuai JsonConverter
boleh membawa kepada StackOverflowException
semasa penyirian, terutamanya dengan objek kompleks. Ini selalunya disebabkan oleh rekursi tak terhingga dalam proses siri dalaman JSON.NET. Walaupun menggunakan terus JsonConvert.SerializeObject()
dengan penukar tersuai anda ialah penyelesaian yang disyorkan, bahagian ini meneroka pendekatan alternatif apabila atribut itu diperlukan.
1. Memperhalusi Kaedah WriteJson
Inti masalah selalunya terletak pada kaedah WriteJson
penukar tersuai anda. Pengendalian kes tepi yang tidak mencukupi boleh mencetuskan gelung tak terhingga. Kaedah WriteJson
yang dipertingkatkan berikut menangani beberapa senario biasa:
<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>
Versi ini secara eksplisit mengendalikan nilai nol dan menggunakan penyelesai kontrak untuk melelang melalui sifat, melangkau sifat diabaikan dan yang ShouldSerialize
mengembalikan palsu. Ia juga mewakilkan siri dengan betul kepada penukar harta jika ada dan boleh menulis, jika tidak, menggunakan siri terus.
2. Panggilan Rekursif dengan Had Saiz Tindanan
Sebagai alternatif, anda boleh menambah semakan kedalaman tindanan dalam kaedah WriteJson
anda untuk mengelakkan pengulangan lari:
<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>
Pendekatan ini memberikan pengecualian deskriptif jika kedalaman rekursi melebihi had yang telah ditetapkan, menghalang StackOverflowException
. Laraskan MaxStackSize
berdasarkan kerumitan objek anda.
Kesimpulan
Walaupun atribut [JsonConvert]
menawarkan kemudahan, menggunakannya dengan penukar tersuai memerlukan pertimbangan yang teliti. Dengan meningkatkan kaedah WriteJson
anda untuk mengendalikan kes tepi dan/atau menggabungkan semakan saiz tindanan, anda boleh mengurangkan risiko StackOverflowException
dengan berkesan semasa penyirian. Ingat bahawa panggilan JsonConvert.SerializeObject()
secara manual kekal sebagai pendekatan yang paling selamat dan boleh dipercayai.
Atas ialah kandungan terperinci Mengapakah menggunakan anotasi `[JsonConvert()]` dengan JsonConverters tersuai kadangkala menghasilkan StackOverflowException, dan bagaimana saya boleh menghalangnya?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!