web-dev-qa-db-fra.com

Comment démarsaler une chaîne JSON échappée dans Go?

j'utilise Sockjs avec Go, mais lorsque le client javascript envoie json au serveur, il l'échappe et l'envoie en tant qu'octet []. j'essaie de comprendre comment analyser le json, afin que je puisse lire les données. mais je reçois cette erreur.

json: impossible de démêler la chaîne dans la valeur Go de type main.Msg

Comment puis-je réparer cela? html.UnescapeString () n'a aucun effet: /

val, err := session.ReadMessage()
if err != nil {
break
}
var msg Msg

err = json.Unmarshal(val, &msg)

fmt.Printf("%v", val)
fmt.Printf("%v", err)

type Msg struct {
    Channel string
    Name    string
    Msg     string
}


//Output
"{\"channel\":\"buu\",\"name\":\"john\", \"msg\":\"doe\"}"
json: cannot unmarshal string into Go value of type main.Msg
22

Vous voudrez peut-être utiliser strconv.Unquote sur votre chaîne JSON en premier :)

Voici un exemple , aimablement fourni par @gregghz:

package main

import (
    "encoding/json"
    "fmt"
    "strconv"
)

type Msg struct {
    Channel string
    Name string
    Msg string
}

func main() {
    var msg Msg
    var val []byte = []byte(`"{\"channel\":\"buu\",\"name\":\"john\", \"msg\":\"doe\"}"`)

    s, _ := strconv.Unquote(string(val))

    err := json.Unmarshal([]byte(s), &msg)

    fmt.Println(s)
    fmt.Println(err)
    fmt.Println(msg.Channel, msg.Name, msg.Msg)
}
38
fresskoma

Vous devez corriger cela dans le code qui génère le JSON.

Quand il s'avère formaté comme ça, il est encodé JSON deux fois. Corrigez ce code qui effectue la génération afin qu'il ne se produise qu'une seule fois.

Voici du JavaScript qui montre ce qui se passe.

// Start with an object
var object = {"channel":"buu","name":"john", "msg":"doe"};

// serialize once
var json = JSON.stringify(object); // {"channel":"buu","name":"john","msg":"doe"}

// serialize twice
json = JSON.stringify(json); // "{\"channel\":\"buu\",\"name\":\"john\",\"msg\":\"doe\"}"
11
user2437417

Comme l'a souligné Crazy Train, il semble que votre entrée soit doublement échappée, provoquant ainsi le problème. Une façon de résoudre ce problème est de vous assurer que la fonction session.ReadMessasge() renvoie une sortie appropriée correctement échappée. Cependant, si ce n'est pas possible, vous pouvez toujours faire ce que x3ro a suggéré et utiliser la fonction golang strconv.Unquote.

Voici un exemple de terrain de jeu en action:

http://play.golang.org/p/GTishI0rwe

2
noj

Quelquefois, strconv.Unquote ne fonctionne pas.

Voici un exemple qui montre le problème et ma solution. (Le lien du terrain de jeu: https://play.golang.org/p/Ap0cdBgiA05 )

Merci pour l'idée "encode deux fois" de @Crazy Train, je viens de la décoder deux fois ...

package main

import (
    "encoding/json"
    "fmt"
    "strconv"
)

type Wrapper struct {
    Data string
}

type Msg struct {
    Photo string
}

func main() {
    var wrapper Wrapper
    var original = `"{\"photo\":\"https:\/\/www.abc.net\/v\/t1.0-1\/p320x320\/123.jpg\"}"`

    _, err := strconv.Unquote(original)

    fmt.Println(err)

    var val []byte = []byte("{\"data\":"+original+"}")
    fmt.Println(string(val))
    err = json.Unmarshal([]byte(val), &wrapper)


    fmt.Println(wrapper.Data)

    var msg Msg
    err = json.Unmarshal([]byte(wrapper.Data), &msg)
    fmt.Println(msg.Photo)
}
1
semicircle21

Vous êtes tombé dans un piège infâme de chaîne d'échappement de JavaScript. Très souvent, les gens sont confrontés (comme moi) au même problème dans Go, lors de la sérialisation de la chaîne JSON avec json.Marshal, par exemple:

in := `{"firstName":"John","lastName":"Dow"}` bytes, err := json.Marshal(in)

json.Marshal échappe les guillemets doubles, produisant le même problème lorsque vous essayez de démarshal les octets dans struct.

Si vous avez rencontré le problème dans Go, consultez Comment sérialiser correctement la chaîne JSON dans Golang poste qui décrit le problème en détail avec une solution.

0
upitau

Les données affichées dans le problème sont stringifiées à certaines fins, dans certains cas, vous pouvez même avoir \ n dans votre chaîne représentant un saut de ligne dans votre json.

Comprenons la manière la plus simple de démarsaler/désérialiser ce type de données en utilisant l'exemple suivant:

  1. La ligne suivante montre les données que vous obtenez de vos sources et que vous souhaitez dersérialiser

    stringifiedData: = "{\ r\n \" a\": \" b\",\r\n \" c\": \" d\"\ r\n}"

  2. Maintenant, supprimez d'abord toutes les nouvelles lignes

    stringifiedData = strings.ReplaceAll (stringifiedData, "\ n", "")

  3. Ensuite, supprimez toutes les citations supplémentaires présentes dans votre chaîne

    stringifiedData = strings.ReplaceAll (stringifiedData, "\\" ","\"")

  4. Convertissons maintenant la chaîne en un tableau d'octets

    dataInBytes: = [] octet (stringifiedData)

  5. Avant de faire unmarshal, définissons la structure de nos données

    jsonObject: = & struct {
    Une chaîne `json:" a "`
    Chaîne C `json:" c "`
    }

  6. Maintenant, vous pouvez dersialiser vos valeurs dans jsonObject

    json.Unmarshal (dataInBytes, jsonObject)}

0
Avinash Dhinwa