douchen3562
2013-05-30 22:01
浏览 371
已采纳

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

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() have 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
  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

6条回答 默认 最新

  • douyou9923 2013-05-30 23:02
    已采纳

    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)
    }
    
    已采纳该答案
    评论
    解决 无用
    打赏 举报
  • dongliang1865 2013-05-30 23:02

    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\"}"
    
    评论
    解决 无用
    打赏 举报
  • douwen2158 2013-05-31 03:36

    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

    评论
    解决 无用
    打赏 举报
  • doujiao6116 2016-07-31 13:24

    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.

    评论
    解决 无用
    打赏 举报
  • dpkrh2444 2018-05-03 09:43

    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)
    }
    
    评论
    解决 无用
    打赏 举报
  • dongyan0629 2019-06-14 19:49

    The data shown in the problem is stringified for some purposes, in some cases you can even have 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 := "{ \"a\": \"b\", \"c\": \"d\" }"

    2. Now, remove all new lines first

      stringifiedData = strings.ReplaceAll(stringifiedData, " ", "")

    3. Then remove all the extra quotes that are present in your string

      stringifiedData = strings.ReplaceAll(stringifiedData, "\\"", "\"")

    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{
      A string `json:"a"`
      C string `json:"c"`
      }

    6. Now, you can dersialize your values into jsonObject

      json.Unmarshal(dataInBytes, jsonObject)}

    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题