4

I want to unmarshal a string that contains JSON, however the Unmarshal function takes a []byte as input.

How can I convert my UTF8 string to []byte?

icza
  • 389,944
  • 63
  • 907
  • 827
Midiparse
  • 4,701
  • 7
  • 28
  • 48

2 Answers2

17

This question is a possible duplicate of How to assign string to bytes array, but still answering it as there is a better, alternative solution:

Converting from string to []byte is allowed by the spec, using a simple conversion:

Conversions to and from a string type

[...]

  1. Converting a value of a string type to a slice of bytes type yields a slice whose successive elements are the bytes of the string.

So you can simply do:

s := "some text"
b := []byte(s) // b is of type []byte

However, the string => []byte conversion makes a copy of the string content (it has to, as strings are immutable while []byte values are not), and in case of large strings it's not efficient. Instead, you can create an io.Reader using strings.NewReader() which will read from the passed string without making a copy of it. And you can pass this io.Reader to json.NewDecoder() and unmarshal using the Decoder.Decode() method:

s := `{"somekey":"somevalue"}`

var result interface{}
err := json.NewDecoder(strings.NewReader(s)).Decode(&result)
fmt.Println(result, err)

Output (try it on the Go Playground):

map[somekey:somevalue] <nil>

Note: calling strings.NewReader() and json.NewDecoder() does have some overhead, so if you're working with small JSON texts, you can safely convert it to []byte and use json.Unmarshal(), it won't be slower:

s := `{"somekey":"somevalue"}`

var result interface{}
err := json.Unmarshal([]byte(s), &result)
fmt.Println(result, err)

Output is the same. Try this on the Go Playground.

Note: if you're getting your JSON input string by reading some io.Reader (e.g. a file or a network connection), you can directly pass that io.Reader to json.NewDecoder(), without having to read the content from it first.

Community
  • 1
  • 1
icza
  • 389,944
  • 63
  • 907
  • 827
  • Another great post that I have quoted. See https://stackoverflow.com/a/62740786/12817546 –  Jul 07 '20 at 09:07
1

just use []byte(s) on the string. for example:

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    s := `{"test":"ok"}`
    var data map[string]interface{}
    if err := json.Unmarshal([]byte(s), &data); err != nil {
        panic(err)
    }
    fmt.Printf("json data: %v", data)
}

check it out on the playground here.

orcaman
  • 6,263
  • 8
  • 54
  • 69