Golang: How To Serialize JSON String in Go Example
Golang json.Marshal() function returns the JSON encoding of interface. Marshal traverses the value of interface recursively. If an encountered value implements the Marshaler interface and is not a nil pointer, Marshal calls its MarshalJSON method to produce JSON.
Golang Serialize JSON String
See the following code.
// hello.go package main import ( "encoding/json" "fmt" ) // Tesla struct type Tesla struct { ProductName string `json:"productName"` ProductPrice string `json:"productPrice"` } func main() { in := `{"productName":"CyberTruck","productPrice": 39900}` bytes, err := json.Marshal(in) if err != nil { panic(err) } var t Tesla err = json.Unmarshal(bytes, &t) if err != nil { panic(err) } fmt.Printf("%+v", t) }
Output
go run hello.go panic: json: cannot unmarshal string into Go value of type main.Tesla goroutine 1 [running]: main.main() /Users/krunal/Desktop/code/go/src/hello/hello.go:25 +0x1d8 exit status 2
So, it will panic and returns an error.
Now, write the following code to see what’s exactly going on.
// hello.go package main import ( "encoding/json" "fmt" ) // Tesla struct type Tesla struct { ProductName string `json:"productName"` ProductPrice string `json:"productPrice"` } func main() { in := `{"productName":"CyberTruck","productPrice": 39900}` bytes, err := json.Marshal(in) if err != nil { panic(err) } fmt.Println(string(bytes)) }
Output
go run hello.go "{\"productName\":\"CyberTruck\",\"productPrice\": 39900}"
When we convert JSON string to usual string, then it does escape the double quotes that is why it returns an error.
So, how to skip escaping?
Well, we have two solutions to correctly Serialize JSON string.
- Use []byte()
- Use json.RawMessage()
Golang []byte
Golang byte is the alias for uint8 and is equivalent to uint8 in all ways. The byte is used, by convention, to distinguish the byte values from 8-bit unsigned integer values.
See the following code.
// hello.go package main import ( "encoding/json" "fmt" ) // Tesla struct type Tesla struct { ProductName string `json:"productName"` ProductPrice string `json:"productPrice"` } func main() { data := `{"productName":"CyberTruck","productPrice":"39900"}` bytes := []byte(data) var t Tesla err := json.Unmarshal(bytes, &t) if err != nil { panic(err) } fmt.Printf("%+v \n", t) fmt.Println(string(bytes)) }
Output
go run hello.go {ProductName:CyberTruck ProductPrice:39900} {"productName":"CyberTruck","productPrice":"39900"}
In the above program, we have converted json to a byte array. So it prevents the double quotes from escaping, and then we have used json.Unmarshal() function.
Golang json.RawMessage()
Golang json package includes a solution for the issue. Golang json has RawMessage type, which Marshalls and Unmarshals without escaping.
So if you need to serialize the JSON string which you need to deserialize later into a struct, do it with json.RawMessage().
See the following code example.
// hello.go package main import ( "encoding/json" "fmt" ) // Tesla struct type Tesla struct { ProductName string `json:"productName"` ProductPrice string `json:"productPrice"` } func main() { data := `{"productName":"CyberTruck","productPrice":"39900"}` rawData := json.RawMessage(data) bytes, err := rawData.MarshalJSON() if err != nil { panic(err) } var t Tesla err = json.Unmarshal(bytes, &t) if err != nil { panic(err) } fmt.Printf("%+v \n", t) fmt.Println(string(bytes)) }
Output
go run hello.go {ProductName:CyberTruck ProductPrice:39900} {"productName":"CyberTruck","productPrice":"39900"}
It returns the same output.
RawMessage is a raw encoded JSON value. It implements Marshaler and Unmarshaler and can be used to delay JSON decoding or precompute a JSON encoding. MarshalJSON returns RawMessage as the JSON encoding of RawMessage.
Serialized struct
The serialized struct is identical to our JSON string.
Now, Let’s make sure that JSON string matches Tesla struct.
See the following code.
// hello.go package main import ( "encoding/json" "fmt" ) // Tesla struct type Tesla struct { ProductName string `json:"productName"` ProductPrice string `json:"productPrice"` } func main() { bytes, err := json.Marshal(Tesla{ ProductName: "CyberTruck", ProductPrice: "39900", }) if err != nil { panic(err) } fmt.Println(string(bytes)) }
Output
go run hello.go {"productName":"CyberTruck","productPrice":"39900"}
Conclusion
So, the Serialized struct works fine with json.Marshal() function but serialized json string directly does not support Marshal() because it escapes double-quotes. So to avoid that, we can use []byte or json.RawMessage() function.
If you want to Serialize JSON String In Golang Correctly, then this is a perfect way.
Finally, Golang Serialize JSON String example is over.