json.Unmarshal nested object into string or []byte
Solution 1
I think what you are looking for is the RawMessage type in the encoding/json
package.
The documentation states:
type RawMessage []byte
RawMessage is a raw encoded JSON object. It implements Marshaler and Unmarshaler and can be used to delay JSON decoding or precompute a JSON encoding.
Here is a working example of using RawMessage:
package main
import (
"encoding/json"
"fmt"
)
var jsonStr = []byte(`{
"id" : 15,
"foo" : { "foo": 123, "bar": "baz" }
}`)
type Bar struct {
Id int64 `json:"id"`
Foo json.RawMessage `json:"foo"`
}
func main() {
var bar Bar
err := json.Unmarshal(jsonStr, &bar)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", bar)
}
Output:
{Id:15 Foo:[123 32 34 102 111 111 34 58 32 49 50 51 44 32 34 98 97 114 34 58 32 34 98 97 122 34 32 125]}
Solution 2
The Foo type is a map[string]string so define Foo correctly:
type Bar struct {
id int64
Foo map[string]string
}
Think that would work better
Solution 3
Defining a type which implements the Unmarshaler
interface gives you access to the []byte
's being parsed.
type Prefs []byte
func (p *Prefs) UnmarshalJSON(b []byte) error {
*p = make(Prefs, len(b))
copy(*p, b)
return nil
}
Related videos on Youtube
Ilia Choly
Favourite Languages: Go TypeScript Python C Lisp Interests: Networking Distributed/Parallel Computing Compilers Security Social Twitter Facebook Github
Updated on April 27, 2021Comments
-
Ilia Choly about 3 years
I'm trying to Unmarshal some json so that a nested object does not get parsed but just treated as a
string
or[]byte
.So I want to get the following:
{ "id" : 15, "foo" : { "foo": 123, "bar": "baz" } }
Unmarshaled into:
type Bar struct { ID int64 `json:"id"` Foo []byte `json:"foo"` }
I get the following error:
json: cannot unmarshal object into Go value of type []uint8
-
J. Holmes over 10 yearsWhy not use
map[string]interface{}
? It also has the advantage of re-Marshalling the correct way. -
Adrian Forsius over 5 years@JamesHolmes this is usually not recommended since this allows for any type, if you don't explicitly want ALL types to be supported don't use empty interface (interface{}), it will cause you more problems than it will solve
-
-
Ilia Choly over 10 yearsSo
[]bytes
->Unmarshal
->map[string]interface{}
->Marshal
->string
... why ? -
Ilia Choly over 10 yearsthat's exactly what I wanted
-
ANisus over 10 yearsTold you so ;) . Glad to help!
-
Ilia Choly over 10 yearsI think this example better communicates what you're saying play.golang.org/p/1XFn6zqME8 . However, it doesn't really answer the question.
-
chovy about 3 yearsi get that output, but how do I use it?