如何在Go中解组转义的JSON字符串?

时间:2013-05-30 22:01:06

标签: json go sockjs

我正在使用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

6 个答案:

答案 0 :(得分:27)

您可能希望首先在JSON字符串上使用strconv.Unquote:)

Here's an example,由@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)
}

答案 1 :(得分:11)

您需要在生成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\"}"

答案 2 :(得分:2)

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

以下是操作中的操场示例:

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

答案 3 :(得分:1)

有时,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)
}

答案 4 :(得分:0)

你从JavaScript中陷入臭名昭着的转义字符串陷阱。当使用json.Marshal序列化JSON字符串时,人们常常在Go中面对(就像我一样)同样的问题,例如:

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

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

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

答案 5 :(得分: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 {
      字符串`json:“ a”`
      C字符串`json:“ c”`
      }

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

      

    json.Unmarshal(dataInBytes,jsonObject)}