如何解析转义的JSON字符串

huangapple go评论92阅读模式
英文:

How to unmarshal an escaped JSON string

问题

我正在使用Go语言的Sockjs,但是当JavaScript客户端向服务器发送json时,它会对其进行转义,并将其作为[]byte发送。我正在尝试解析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
}

//输出
"{"channel":"buu","name":"john", "msg":"doe"}"
json: 无法将字符串解组为类型为main.Msg的Go值

英文:

I am using Sockjs with Go, but when the JavaScript client send json to the server it escapes it, and send's it as a []byte. I'm trying to figure out how to parse the json, so that i can read the data. but I get this error.

> json: cannot unmarshal string into Go value of type main.Msg

How can I fix this? html.UnescapeString() has no effect.

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

得分: 81

你可能想先使用strconv.Unquote来处理你的JSON字符串 如何解析转义的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)
}
英文:

You might want to use strconv.Unquote on your JSON string first 如何解析转义的JSON字符串

Here's an example, kindly provided by @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

得分: 17

你需要在生成JSON的代码中修复这个问题。

当它被格式化成这样时,它被JSON编码了两次。修复生成代码的部分,使其只发生一次。

这里是一些展示情况的JavaScript代码。

// 从一个对象开始
var object = {"channel":"buu","name":"john", "msg":"doe"};

// 序列化一次
var json = JSON.stringify(object); // {"channel":"buu","name":"john","msg":"doe"}

// 序列化两次
json = JSON.stringify(json); // "{"channel":"buu","name":"john","msg":"doe"}"

英文:

You need to fix this in the code that is generating the JSON.

When it turns out formatted like that, it is being JSON encoded twice. Fix that code that is doing the generating so that it only happens once.

Here's some JavaScript that shows what's going on.

// 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

得分: 13

有时候,strconv.Unquote 不起作用。

这里有一个例子展示了问题和我的解决方案。
(playground链接:https://play.golang.org/p/Ap0cdBgiA05)

感谢 @Crazy Train 的“encodes twice”想法,我只是解码了两次...

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)
}
英文:

Sometimes, strconv.Unquote doesn't work.

Heres an example shows the problem and my solution.
(The playground link: https://play.golang.org/p/Ap0cdBgiA05)

Thanks for @Crazy Train's "encodes twice" idea, I just decoded it twice ...

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

得分: 3

正如Crazy Train指出的那样,看起来你的输入被双重转义了,因此导致了问题。修复这个问题的一种方法是确保函数session.ReadMessasge()返回适当的输出并适当地进行转义。然而,如果这不可能,你可以像x3ro建议的那样使用golang函数strconv.Unquote

这里有一个示例,展示了它的使用方法:

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

英文:

As Crazy Train pointed out, it appears that your input is doubly escaped, thus causing the issue. One way to fix this is to make sure that the function session.ReadMessasge() returns proper output that is escaped appropriately. However, if that's not possible, you can always do what x3ro suggested and use the golang function strconv.Unquote.

Here's a playground example of it in action:

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

答案5

得分: 0

The data shown in the problem is stringified for some purposes, in some cases you can even have <strong>\n</strong> in your string representing break of line in your json.

Let's understand the easiest way to unmarshal/deserialize this kind of data using the following example:

  1. Next line shows the data you get from your sources and want to derserialize
    > stringifiedData := "{\r\n &quot;a&quot;: &quot;b&quot;,\r\n &quot;c&quot;: &quot;d&quot;\r\n}"

  2. Now, remove all new lines first
    > stringifiedData = strings.ReplaceAll(stringifiedData, "\n", "")

  3. Then remove all the extra quotes that are present in your string
    > stringifiedData = strings.ReplaceAll(stringifiedData, "\&quot;", "&quot;")

  4. Let's now convert the string into a byte array
    > dataInBytes := []byte(stringifiedData)

  5. Before doing unmarshal, let's define structure of our data
    > jsonObject := &struct{ <br>
    > A string `json:"a"` <br>
    > C string `json:"c"` <br>
    > }

  6. Now, you can dersialize your values into jsonObject
    >json.Unmarshal(dataInBytes, jsonObject)

英文:

The data shown in the problem is stringified for some purposes, in some cases you can even have <strong>\n</strong> in your string representing break of line in your json.

Let's understand the easiest way to unmarshal/deserialize this kind of data using the following example:

  1. Next line shows the data you get from your sources and want to derserialize
    > stringifiedData := "{\r\n &quot;a&quot;: &quot;b&quot;,\r\n &quot;c&quot;: &quot;d&quot;\r\n}"

  2. Now, remove all new lines first
    > stringifiedData = strings.ReplaceAll(stringifiedData, "\n", "")

  3. Then remove all the extra quotes that are present in your string
    > stringifiedData = strings.ReplaceAll(stringifiedData, "\&quot;", "&quot;")

  4. Let's now convert the string into a byte array
    > dataInBytes := []byte(stringifiedData)

  5. Before doing unmarshal, let's define structure of our data
    > jsonObject := &struct{ <br>
    > A string `json:"a"` <br>
    > C string `json:"c"` <br>
    > }

  6. Now, you can dersialize your values into jsonObject
    >json.Unmarshal(dataInBytes, jsonObject)}

答案6

得分: -1

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

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

json.Marshal会转义双引号,导致在尝试将字节反序列化为结构体时出现相同的问题。

如果你在Go中遇到了这个问题,请查看如何正确序列化Golang中的JSON字符串一文,该文章详细描述了这个问题,并提供了解决方案。

英文:

You got into infamous escaped string pitfall from JavaScript. Quite often people face (as I did) the same issue in Go, when serializing JSON string with json.Marshal, e.g.:

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

json.Marshal escapes double quotes, producing the same issue when you try to unmarshal bytes into struct.

If you faced the issue in Go, have a look at How To Correctly Serialize JSON String In Golang post which describes the issue in details with solution to it.

huangapple
  • 本文由 发表于 2013年5月31日 06:01:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/16846553.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定