Maison > développement back-end > Golang > le corps du texte

L'appel de json.Unmarshal dans la fonction UnmarshalJSON ne provoque pas de débordement de pile

WBOY
Libérer: 2024-02-12 08:27:09
avant
578 Les gens l'ont consulté

在 UnmarshalJSON 函数内调用 json.Unmarshal 不会导致堆栈溢出

Lors du traitement des données JSON, nous utilisons généralement la fonction json.Unmarshal pour analyser la chaîne JSON dans une structure en langage Go. Cependant, l'appel de la fonction json.Unmarshal dans la fonction UnmarshalJSON peut provoquer une erreur de débordement de pile. En effet, la fonction UnmarshalJSON s'appelle à nouveau lors de l'analyse des données JSON, provoquant une boucle infinie. Pour éviter cela, nous pouvons utiliser la méthode Decode de json.Decoder pour analyser les données JSON au lieu d'appeler directement la fonction json.Unmarshal. Cela garantit que les problèmes de débordement de pile ne se produiront pas et garantit la robustesse et les performances du code.

Contenu de la question

Je souhaite effectuer quelques étapes supplémentaires pour initialiser mon implémentation UnmarshalJSON 中的数据结构。在该实现中调用 json.Unmarshal(b, type), ce qui entraîne naturellement un débordement de pile.

Le décodeur JSON continue d'essayer de trouver s'il existe des personnalisations UnmarshalJSON 实现,然后再次调用 json.Unmarshal.

Y a-t-il une autre façon de procéder ? Le simple fait d'appeler l'implémentation par défaut sous-jacente ne provoquerait-il pas ce problème ?

Solution

Un moyen simple et courant d'éviter/prévenir cela consiste à utiliser le mot-clé type et à utiliser le type conversion pour transmettre une valeur de ce type (la valeur peut être utilisée si vous avez une valeur primitive, le type la conversion est possible car le nouveau type a le type primitif comme type sous-jacent).

Cela fonctionne car le mot-clé type crée un nouveau type, et le nouveau type n'aura aucune méthode (il n'héritera pas des méthodes du type de base).

Cela entraînera-t-il une surcharge d'exécution ? Non. Cité de Spécification : Conversion :

Voyons un exemple. Nous en avons un avec les chiffres AgePerson 类型,并且我们要确保 Age 不能为负数(小于 0).

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func (p *Person) UnmarshalJSON(data []byte) error {
    type person2 Person
    if err := json.Unmarshal(data, (*person2)(p)); err != nil {
        return err
    }

    // Post-processing after unmarshaling:
    if p.Age < 0 {
        p.Age = 0
    }
    return nil
}
Copier après la connexion

Testez-le :

var p *Person
fmt.Println(json.Unmarshal([]byte(`{"name":"Bob","age":10}`), &p))
fmt.Println(p)

fmt.Println(json.Unmarshal([]byte(`{"name":"Bob","age":-1}`), &p))
fmt.Println(p)
Copier après la connexion

Sortie (essayez-le sur Go Playground) :

<nil>
&{Bob 10}
<nil>
&{Bob 0}
Copier après la connexion

Bien sûr, la même technique fonctionne également pour les commissaires personnalisés (MarshalJSON()) :

func (p *Person) MarshalJSON() ([]byte, error) {
    // Pre-processing before marshaling:
    if p.Age < 0 {
        p.Age = 0
    }

    type person2 Person
    return json.Marshal((*person2)(p))
}
Copier après la connexion

Testez-le :

p = &Person{"Bob", 10}
fmt.Println(json.NewEncoder(os.Stdout).Encode(p))
p = &Person{"Bob", -1}
fmt.Println(json.NewEncoder(os.Stdout).Encode(p))
Copier après la connexion

Sortie (dans le même exemple Go Playground) :

{"name":"Bob","age":10}
<nil>
{"name":"Bob","age":0}
<nil>
Copier après la connexion

Un problème très similaire se produit lorsque vous utilisez la méthode fmt 的自定义文本表示定义 String() string pour un package> et que vous souhaitez utiliser la représentation sous forme de chaîne par défaut que vous avez modifiée. En savoir plus ici : Différence entre t et *t

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!

Étiquettes associées:
source:stackoverflow.com
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal