Как размонтировать сбежавшую строку 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.
Давайте разберемся в простейшем способе демарширования/десериализации данных такого типа на следующем примере:
-
Следующая строка показывает данные, которые вы получаете из своих источников и хотите дерисализировать
stringifiedData: = "{\ r\n \" a\": \" b\",\r\n \" c\": \" d\"\ r\n}"
-
Теперь сначала удалите все новые строки
stringifiedData = strings.ReplaceAll(stringifiedData, "\n", "")
-
Затем удалите все лишние кавычки, которые присутствуют в вашей строке
stringifiedData = strings.ReplaceAll(stringifiedData, "\\" ","\"")
-
Пусть теперь преобразовать строку в байтовый массив
dataInBytes: = [] byte (stringifiedData)
-
Прежде чем делать демаршал, давайте определим структуру наших данных
jsonObject: = & struct {Строка json:"a"
B строка json:"c"
}
-
Теперь вы можете деерсифицировать ваши значения в jsonObject
json.Unmarshal(dataInBytes, jsonObject)}