Go语言 如何解封转义的JSON字符串

ztigrdn8  于 2023-11-14  发布在  Go
关注(0)|答案(7)|浏览(149)

我在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
67up9zun

67up9zun1#

你可能想先在你的JSON字符串上使用strconv.Unquote:)
Here's an example,由@ gregeland友情提供:

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

字符串

4ktjp1zp

4ktjp1zp2#

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

字符串

hc8w905p

hc8w905p3#

有时候strconv.Unquote不起作用。
这里有一个例子显示了问题和我的解决方案。(操场链接:https://play.golang.org/p/Ap0cdBgiA05
感谢@疯狂火车的“编码两次”的想法,我只是解码了两次......

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

字符串

cedebl8k

cedebl8k4#

正如Crazy Train所指出的,似乎你的输入被双重转义了,从而导致了这个问题。解决这个问题的一种方法是确保函数session.ReadMessasge()返回正确的输出,并且被适当地转义。但是,如果这不可能,你可以按照x3ro的建议使用golang函数strconv.Unquote
这里有一个操场上的例子:
http://play.golang.org/p/GTishI0rwe

yjghlzjz

yjghlzjz5#

以下是我的解决方案:https://go.dev/play/p/iLUCgUFIyKk它基于@mccle21的解决方案,但不需要额外的Wrapper结构体,go json包可以直接解封为字符串。

package main

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

type Msg struct {
    Photo string
}

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

    _, err := strconv.Unquote(original)

    fmt.Println(err)

    var data string
    err = json.Unmarshal([]byte(original), &data)
    fmt.Println(data)

    var msg Msg
    err = json.Unmarshal([]byte(data), &msg)
    fmt.Println(msg.Photo)
}

字符串

3htmauhk

3htmauhk6#

问题中显示的数据是字符串化的,在某些情况下,你甚至可以在你的字符串中使用**\n**来表示你的json中的换行符。
让我们使用下面的示例来了解解组/解压缩此类数据的最简单方法:
1.下一行显示了从源代码中获得的并希望反序列化的数据
stringifiedData:=“{\r\n \“a":\“B",\r\n \“c":\“d"\r\n}”
1.现在,首先删除所有新行
stringifiedData = strings.ReplaceAll(stringifiedData,“\n”,“”)
1.然后删除字符串中所有多余的引号
stringifiedData = strings.ReplaceAll(stringifiedData,“\"",“"”)
1.现在让我们将字符串转换为字节数组
dataIncident:= []byte(stringifiedData)
1.在进行解组之前,让我们定义数据的结构
jsonObject:= &struct{
一个字符串json:“a”
C字符串json:“c”
}
1.现在,您可以将值去尺寸化为jsonObject
json.Unmarshal(dataInmarshal,jsonObject)}

s4chpxco

s4chpxco7#

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

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

字符串
json.Marshal转义双引号,当您尝试将字节解组到结构中时会产生相同的问题。
如果你在Go中遇到了这个问题,看看How To Correctly Serialize JSON String In Golang帖子,它详细描述了这个问题的解决方案。

相关问题