Maison > développement back-end > C++ > Pourquoi l'utilisation de l'annotation `[JsonConvert()]` avec des JsonConverters personnalisés entraîne-t-elle parfois une StackOverflowException, et comment puis-je l'empêcher ?

Pourquoi l'utilisation de l'annotation `[JsonConvert()]` avec des JsonConverters personnalisés entraîne-t-elle parfois une StackOverflowException, et comment puis-je l'empêcher ?

Patricia Arquette
Libérer: 2025-01-20 15:25:15
original
704 Les gens l'ont consulté

Why does using the `[JsonConvert()]` annotation with custom JsonConverters sometimes result in a StackOverflowException, and how can I prevent it?

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 WriteJsonMé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>
Copier après la connexion

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>
Copier après la connexion

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!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal