JSON.NET StackOverflowException et l'[JsonConvert]
Attribut
Appliquer l'attribut [JsonConvert]
à un JsonConverter
personnalisé peut conduire à StackOverflowException
lors de la sérialisation, notamment avec des objets complexes. Cela est souvent dû à une récursivité infinie au sein du processus de sérialisation interne de JSON.NET. Bien que l'utilisation directe de JsonConvert.SerializeObject()
avec votre convertisseur personnalisé soit la solution recommandée, cette section explore des approches alternatives lorsque l'attribut est nécessaire.
1. Affiner la WriteJson
Méthode
Le cœur du problème réside souvent dans la WriteJson
méthode de votre convertisseur personnalisé. Une gestion insuffisante des cas extrêmes peut déclencher la boucle infinie. La méthode WriteJson
améliorée suivante répond à plusieurs scénarios courants :
<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>
Cette version gère explicitement les valeurs nulles et utilise le résolveur de contrat pour parcourir les propriétés, en ignorant les propriétés ignorées et celles où ShouldSerialize
renvoie false. Il délègue également correctement la sérialisation au convertisseur de propriété s'il en existe un et peut écrire, sinon en utilisant directement le sérialiseur.
2. Appel récursif avec limite de taille de pile
Vous pouvez également ajouter une vérification de la profondeur de la pile dans votre WriteJson
méthode pour éviter une récursion incontrôlée :
<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>
Cette approche lève une exception descriptive si la profondeur de récursion dépasse une limite prédéfinie, empêchant le StackOverflowException
. Ajustez MaxStackSize
en fonction de la complexité de votre objet.
Conclusion
Bien que l'attribut [JsonConvert]
soit pratique, son utilisation avec des convertisseurs personnalisés nécessite une attention particulière. En améliorant votre méthode WriteJson
pour gérer les cas extrêmes et/ou en incorporant une vérification de la taille de la pile, vous pouvez atténuer efficacement le risque de StackOverflowException
pendant la sérialisation. N'oubliez pas qu'appeler manuellement JsonConvert.SerializeObject()
reste l'approche la plus sûre et la plus fiable.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!