3

This is a very weird situation but I need to convert a stringified json to something valid that I can unmarshall with:

"{\"hello\": \"hi\"}"

I want to be able to unmarshall this into a struct like this:

type mystruct struct {
    Hello string `json:"hello,string"`
}

I know normally the unmarshall takes bytes but Im trying to convert what I currently get into something structified. Any suggestions?

3
  • 1
    If str is a string value, what's not to like about err := json.Unmarshal([]byte(str), &result)? Commented May 21, 2020 at 21:21
  • 1
    Have you made any attempt? Can you show that attempt? What problem(s) did you encounter? Commented May 21, 2020 at 21:24
  • Yes I made an effort. It doesn't work with unmarshal: play.golang.org/p/uTBSZz-GPcI Commented May 22, 2020 at 19:10

1 Answer 1

2

The issue is that the encoding/json package accepts well-formed JSON, in this case the initial JSON that you have has escaped quotes, first you have to unescape them, one way to do this is by using the strconv.Unquote function, here's a sample snippet:

package main

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

type mystruct struct {
    Hello string `json:"hello,omitempty"`
}

func main() {
    var rawJSON []byte = []byte(`"{\"hello\": \"hi\"}"`)

    s, _ := strconv.Unquote(string(rawJSON))

    var val mystruct
    if err := json.Unmarshal([]byte(s), &val); err != nil {
        // handle error
    }

    fmt.Println(s)
    fmt.Println(err)
    fmt.Println(val.Hello)
}
Sign up to request clarification or add additional context in comments.

4 Comments

Careful here. strconv.Unquote applies Go escaping rules, which are different from JSON escaping. It's highly unlikely that the input is a quoted Go string literal. Chances are that this is a double-encoded JSON document, in which case you'd just unmarshal twice. Point is, undoing the escaping must consider what the producer of this string did.
Yeah, the API Im seeing this double quoted is a bug. But temporarily I need to utilize the API. I agree that this is very rare and should be careful. However, I didn't see anyone else who know how to manage such data. Im curious, how would you "unmarshal twice"? The unmarshal input would be a byte only right? The first time I unmarshall it has to be directly to a string? or a byte stream?
Here's an example of a double-unmarshal: play.golang.org/p/5eKwOG5tmfS (I took your example and whacked on it a bit)
I see. I didn't realize we could unmarshal to a string. I assumed it must only be to a struct. This is also a very good answer. Different approach than Tristian. You should post this as a separate anser.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.