Как размонтировать сбежавшую строку JSON в Go?

am использует Sockjs с Go, но когда клиент javascript отправляет json на сервер, он ускользает от него и отправляет его в качестве [] байта. Я пытаюсь понять, как разбирать json, чтобы я мог читать данные. но я получаю эту ошибку.

json: не может отключить строку в значение Go типа main.Msg

Как я могу это исправить? html.UnescapeString() не действуют:/

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

Ответ 1

Возможно, вы захотите strconv.Unquote использовать strconv.Unquote в строке JSON :)

Вот пример, любезно предоставленный @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)
}

Ответ 2

Вам нужно исправить это в коде, который генерирует JSON.

Когда он получается таким форматированным, он дважды кодируется JSON. Исправьте этот код, который выполняет генерирование так, чтобы он выполнялся только один раз.

Вот какой JavaScript, который показывает, что происходит.

// 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\"}"

Ответ 3

Как отметил Crazy Train, кажется, что ваш вход вдвойне экранирован, что вызывает проблему. Один из способов исправить это - убедиться, что функция session.ReadMessasge() возвращает правильный вывод, который экранирован соответствующим образом. Однако, если это невозможно, вы всегда можете сделать то, что предложил x3ro, и использовать функцию golang strconv.Unquote.

Вот пример игры в действии:

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

Ответ 4

Иногда strconv.Unquote не работает.

Вот пример показывает проблему и мое решение. (Ссылка на игровую площадку: https://play.golang.org/p/Ap0cdBgiA05)

Спасибо за @Crazy Train "кодирует дважды" идею, я просто расшифровал ее дважды...

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)
}

Ответ 5

Вы попали в печально известную бегущую строку из JavaScript. Довольно часто люди сталкиваются (как и я) с той же проблемой в Go, когда сериализуют строку JSON с json.Marshal, например:

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

json.Marshal избегает двойных кавычек, создавая ту же проблему, когда вы пытаетесь развязать байты в struct.

Если вы столкнулись с проблемой в Go, посмотрите Как правильно сериализировать строку JSON в Golang, в которой подробно описывается проблема с решение для него.

Ответ 6

Данные, показанные в задаче, для некоторых целей являются строковыми, в некоторых случаях в строке может даже присутствовать \n, представляющий разрыв строки в вашем json.

Давайте разберемся в простейшем способе демарширования/десериализации данных такого типа на следующем примере:

  1. Следующая строка показывает данные, которые вы получаете из своих источников и хотите дерисализировать

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

  2. Теперь сначала удалите все новые строки

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

  3. Затем удалите все лишние кавычки, которые присутствуют в вашей строке

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

  4. Пусть теперь преобразовать строку в байтовый массив

    dataInBytes: = [] byte (stringifiedData)

  5. Прежде чем делать демаршал, давайте определим структуру наших данных

    jsonObject: = & struct {Строка json:"a" B строка json:"c" }

  6. Теперь вы можете деерсифицировать ваши значения в jsonObject

    json.Unmarshal(dataInBytes, jsonObject)}