41

我在 Go 中使用 Sockjs,但是当 JavaScript 客户端将 json 发送到服务器时,它会对其进行转义,并将其作为 [] 字节发送。我试图弄清楚如何解析 json,以便我可以读取数据。但我得到这个错误。

json:无法将字符串解组为 main.Msg 类型的 Go 值

我怎样才能解决这个问题?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
4

6 回答 6

68

您可能想先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)
}
于 2013-05-30T23:02:46.593 回答
14

您需要在生成 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\"}"
于 2013-05-30T23:02:55.133 回答
10

有时,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)
}
于 2018-05-03T09:43:59.890 回答
3

正如 Crazy Train 指出的那样,您的输入似乎被双重转义,从而导致了问题。解决此问题的一种方法是确保函数session.ReadMessasge()返回正确转义的正确输出。但是,如果这不可能,您始终可以按照 x3ro 的建议进行操作并使用 golang 函数strconv.Unquote

这是它在操场上的一个例子:

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

于 2013-05-31T03:36:07.623 回答
0

你陷入了臭名昭著的 JavaScript转义字符串陷阱。在使用 json.Marshal 序列化 JSON 字符串时,人们经常在 Go 中遇到(和我一样)同样的问题,例如:

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

json.Marshal 转义双引号,当您尝试将字节解组为结构时会产生相同的问题。

如果您在 Go 中遇到问题,请查看How To Correctly Serialize JSON String In Golang帖子,该帖子详细描述了该问题及其解决方案。

于 2016-07-31T13:24:24.400 回答
0

出于某些目的,问题中显示的数据是字符串化的,在某些情况下,您甚至可以在字符串中使用\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{
    A 字符串 `json:"a"`
    C 字符串 `json:"c"`
    }

  6. 现在,您可以将值反序列化为 jsonObject

    json.Unmarshal(dataInBytes, jsonObject)}

于 2019-06-14T19:49:18.363 回答