How to unmarshal escaped string

Issue

I have a dumb question regarding JSON string unmarshalling in Go

Here’s the code:

package main

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

func main() {
    s := "{\"just_a_key\":\"Some text \"some quoted text\"\"}"
    fmt.Println(s)
    buf := bytes.NewBufferString(s)
    data := make(map[string]string)

    err := json.Unmarshal(buf.Bytes(), &data)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(data)
}

The output:

{"just_a_key":"Some text "some quoted text""}
invalid character 's' after object key:value pair

Seems like unmarshaller really hates ‘\"’ sequence. How can I fix the issue?

Solution

Your input is not valid JSON. To have a double quote inside a JSON string, you have to escape it. Use the \" sequence for a double quote character.

But since you’re using an interpreted Go string literal to specify the JSON text, the \" sequence also have to be escaped according to the Go interpreted rules, where a backslash is \\ and the double quote is \", so the JSON \" sequence must appear as \\\" in a Go interpreted string literal:

s := "{\"just_a_key\":\"Some text \\\"some quoted text\\\"\"}"

With this change output is (try it on the Go Playground):

{"just_a_key":"Some text \"some quoted text\""}
map[just_a_key:Some text "some quoted text"]

It’s much easier and cleaner if you use raw string literal (where no Go escaping is needed, just the JSON escaping):

s := `{"just_a_key":"Some text \"some quoted text\""}`

This will output the same. Try this one on the Go Playground.

Answered By – icza

Answer Checked By – Robin (GoLangFix Admin)

Leave a Reply

Your email address will not be published.