Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the best way to maintain un-parsed JSON fields in Go?

I'd like to decode a JSON blob into a Go struct, manipulate on it, and encode it back to JSON. However, there are dynamic fields in the JSON that aren't relevant to my struct and I want to maintain them when I serialize back to JSON.

For example:

{ "name": "Joe Smith", 
  "age": 42, 
  "phone": "614-555-1212", 
  "debug": True, 
  "codeword": "wolf" }

type Person struct {
    Name string
    Age uint
    Phone string
}

var p Person
json.Unmarshal(data, &p)
// Happy birthday
p.Age++
data, _ = json.Marshal(p)

// Any way to maintain the "debug" and "codeword" fields -- which might not
// be known ahead of time?

I know one possibility is to decode everything into a map[string]interface{} but boy, do things get ugly when you do that.

Is there any way to have the best of both worlds?

like image 448
Joe Shaw Avatar asked Sep 12 '13 15:09

Joe Shaw


People also ask

How do you Unmarshal a JSON?

To parse JSON, we use the Unmarshal() function in package encoding/json to unpack or decode the data from JSON to a struct. Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v. Note: If v is nil or not a pointer, Unmarshal returns an InvalidUnmarshalError.

How does JSON Unmarshal work in Golang?

Marshal function, will take JSON data and translate it back into Go data. You provide json. Unmarshal with the JSON data as well as the Go variable to put the unmarshalled data into and it will either return an error value if it's unable to do it, or a nil error value if it succeeded.

How do you Unmarshal in Go?

Unmarshal is the contrary of marshal. It allows you to convert byte data into the original data structure. In go, unmarshaling is handled by the json. Unmarshal() method.


1 Answers

With encoding/json there's no way to do decode a struct and save unknown fields at the same level for posterior re-encoding. What you can do is choose not to decode part of the struct by using the json.RawMessage type, along the lines of:

type Person struct {
    Name    string
    Address json.RawMessage
}

You might workaround that by implementing your own Unmarshaler that decodes the document into a map and saves the unknown keys in a field of the struct, and then have a counterpart Marshaler that puts the fields back before marshaling.

Just out of curiosity, the feature you're looking for does exist in labix.org/v2/mgo/bson, via the inline tag flag, and the goal was to solve precisely the use case you're describing.

like image 135
Gustavo Niemeyer Avatar answered Sep 28 '22 03:09

Gustavo Niemeyer