JSON Encoding in Go: Dealing with Sensitive Fields
// | |
// Golang example: Handling sensitive struct fields when JSON encoding. | |
// | |
// Blog Post: http://blakecaldwell.net/blog/2015/1/20/json-encoding-in-go-dealing-with-sensitive-fields.html | |
// | |
// Try this in the Go Playground: https://play.golang.org/p/Du5ztx6zjC | |
// | |
// Author | |
// ------ | |
// | |
// Blake Caldwell | |
// http://blakecaldwell.net | |
// http://twitter.com/blakecaldwell | |
// | |
// Script Output | |
// ------------- | |
// | |
// Person: { | |
// "FirstName": "Arthur", | |
// "LastName": "Dent", | |
// "AuthToken": "green-ones" | |
// } | |
// SafePerson: { | |
// "FirstName": "Arthur", | |
// "LastName": "Dent" | |
// } | |
// PrettySafePerson - AuthToken has value: { | |
// "FirstName": "Arthur", | |
// "LastName": "Dent", | |
// "AuthToken": "green-ones" | |
// } | |
// PrettySafePerson - AuthToken is empty: { | |
// "FirstName": "Arthur", | |
// "LastName": "Dent" | |
// } | |
// PublicPerson: { | |
// "FirstName": "Arthur", | |
// "LastName": "Dent" | |
// } | |
// PublicPerson with AuthToken: { | |
// "FirstName": "Arthur", | |
// "LastName": "Dent", | |
// "AuthToken": "green-ones" | |
// } | |
// | |
package main | |
import ( | |
"encoding/json" | |
"fmt" | |
) | |
// Person struct that includes all fields in JSON | |
type Person struct { | |
FirstName string | |
LastName string | |
AuthToken string | |
} | |
// SafePerson omits AuthToken in JSON | |
type SafePerson struct { | |
FirstName string | |
LastName string | |
AuthToken string `json:"-"` | |
} | |
// PrettySafePerson omits AuthToken if it doesn't have a value | |
type PrettySafePerson struct { | |
FirstName string | |
LastName string | |
AuthToken string `json:",omitempty"` | |
} | |
// PublicPerson decorates a Person, hiding AuthToken by default | |
type PublicPerson struct { | |
*Person | |
AuthToken string `json:",omitempty"` | |
} | |
// IncludeAuthToken unhides the Person's AuthToken | |
func (p *PublicPerson) IncludeAuthToken() { | |
p.AuthToken = p.Person.AuthToken | |
} | |
func main() { | |
// Print JSON for a Person, which shows all fields | |
person := Person{ | |
FirstName: "Arthur", | |
LastName: "Dent", | |
AuthToken: "green-ones", | |
} | |
printJSON("Person", person) | |
// Print JSON for a SafePerson, which hides AuthToken because it's always omitted | |
safePerson := SafePerson{ | |
FirstName: "Arthur", | |
LastName: "Dent", | |
AuthToken: "green-ones", | |
} | |
printJSON("SafePerson", safePerson) | |
// Print JSON for PrettySafePerson, which hides AuthToken if it's empty | |
prettySafePerson := PrettySafePerson{ | |
FirstName: "Arthur", | |
LastName: "Dent", | |
AuthToken: "green-ones", | |
} | |
printJSON("PrettySafePerson - AuthToken has value", prettySafePerson) | |
prettySafePerson.AuthToken = "" | |
printJSON("PrettySafePerson - AuthToken is empty", prettySafePerson) | |
// Print JSON for PublicPerson, which decorates Person, hiding AuthToken by overriding it | |
pe := PublicPerson{ | |
Person: &person, | |
} | |
printJSON("PublicPerson", pe) | |
// Print JSON for the same PublicPerson after including AuthToken | |
pe.IncludeAuthToken() | |
printJSON("PublicPerson with AuthToken", pe) | |
} | |
func printJSON(name string, thing interface{}) { | |
jsonBytes, err := json.MarshalIndent(thing, "", " ") | |
if err != nil { | |
fmt.Printf("ERROR: %s\n", err) | |
return | |
} | |
fmt.Printf("%s: %s\n", name, string(jsonBytes)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment