英文:
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字符串
这里有一个例子,由@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
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:
答案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:
-
Next line shows the data you get from your sources and want to derserialize
> stringifiedData := "{\r\n "a": "b",\r\n "c": "d"\r\n}" -
Now, remove all new lines first
> stringifiedData = strings.ReplaceAll(stringifiedData, "\n", "") -
Then remove all the extra quotes that are present in your string
> stringifiedData = strings.ReplaceAll(stringifiedData, "\"", """) -
Let's now convert the string into a byte array
> dataInBytes := []byte(stringifiedData) -
Before doing unmarshal, let's define structure of our data
> jsonObject := &struct{ <br>
> A string `json:"a"` <br>
> C string `json:"c"` <br>
> } -
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:
-
Next line shows the data you get from your sources and want to derserialize
> stringifiedData := "{\r\n "a": "b",\r\n "c": "d"\r\n}" -
Now, remove all new lines first
> stringifiedData = strings.ReplaceAll(stringifiedData, "\n", "") -
Then remove all the extra quotes that are present in your string
> stringifiedData = strings.ReplaceAll(stringifiedData, "\"", """) -
Let's now convert the string into a byte array
> dataInBytes := []byte(stringifiedData) -
Before doing unmarshal, let's define structure of our data
> jsonObject := &struct{ <br>
> A string `json:"a"` <br>
> C string `json:"c"` <br>
> } -
Now, you can dersialize your values into jsonObject
>json.Unmarshal(dataInBytes, jsonObject)}
答案6
得分: -1
你在JavaScript中遇到了臭名昭著的转义字符串陷阱。在Go中,人们经常面临相同的问题(就像我一样),当使用json.Marshal序列化JSON字符串时,例如:
in := `{"firstName":"John","lastName":"Dow"}`
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 := `{"firstName":"John","lastName":"Dow"}`
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论