Documentation ¶
Overview ¶
Package checkjson provides functions for checking JSON object keys against struct member names/tags to see if they will be decoded using encoding/json package.
There are several options: Validate returns an error on the first key:value pair that won't decode, and UnknownJSONKeys returns a slice of all the keys that won't be decoded.
A complementary function MissingJSONKeys provides a slice of struct members that won't be set by the JSON object using encoding/json.
NOTE: this package DOES NOT support recursive struct definitions.
Index ¶
- func ExistingJSONKeys(b []byte, val interface{}) ([]string, error)
- func IgnoreOmitemptyTag(ok ...bool)
- func MissingJSONKeys(b []byte, val interface{}) ([]string, error)
- func ReadJSONFile(file string) ([][]byte, error)
- func ReadJSONReader(r io.Reader) ([]byte, error)
- func ResolveJSONError(data []byte, err error) error
- func SetKeysToIgnore(s ...string)
- func SetMembersToIgnore(s ...string)
- func UnknownJSONKeys(b []byte, val interface{}) ([]string, error)
- func Validate(b []byte, val interface{}) error
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ExistingJSONKeys ¶
ExistingJSONKeys returns a list of fields of the struct 'val' that WILL BE set by unmarshaling the JSON object. It is the complement of MissingJSONKeys. For nested structs, field labels are the dot-notation hierachical path for a JSON key. Specific struct fields can be igored when scanning the JSON object by declaring them using SetMembersToIgnore. (NOTE: JSON object keys and tags are treated as case insensitive, i.e., there is no distiction between "keylabel":"value" and "Keylabel":"value" and "keyLabel":"value".)
For embedded structs, both the field label for the embedded struct as well as the dot-notation label for that struct's fields are included in the list. Thus,
type Person struct { Name NameInfo Sex string } type NameInfo struct { First, Middle, Last string } jobj := []byte(`{"name":{"first":"Jonnie","middle":"Q","last":"Public"},"sex":"unkown"}`) p := Person{} fields, _ := ExistingKeys(jobj, p) fmt.Println(fields) // prints: [Name Name.First Name.Middle Name.Last Sex]
Struct fields that have JSON tag "-" are never returned. Struct fields with the tag attribute "omitempty" will, by default NOT be returned unless the keys exist in the JSON object. If you want to know if "omitempty" struct fields are actually in the JSON object, then call IgnoreOmitEmptyTag(false) prior to using ExistingJSONKeys.
func IgnoreOmitemptyTag ¶
func IgnoreOmitemptyTag(ok ...bool)
IgnoreOmitemptyTag determines whether a `json:",omitempty"` tag is recognized or not with respect to the JSON object. By default MissingJSONKeys will not include struct fields that are tagged with "omitempty" in the list of missing JSON keys. If the function is toggled or passed the optional argument 'false' then missing JSON keys may include those for struct fields with the 'omitempty' JSON tag.
Calling IgnoreOmitemptyTag with no arguments toggles the handling on/off. If the alternative argument is passed, then the argument value determines the "omitempty" handling behavior.
func MissingJSONKeys ¶
MissingJSONKeys returns a list of fields of a struct that will NOT be set by unmarshaling the JSON object; rather, they will assume their default values. For nested structs, field labels are the dot-notation hierachical path for the missing JSON key. Specific struct fields can be igored when scanning the JSON object by declaring them using SetMembersToIgnore(). (NOTE: JSON object keys and tags are treated as case insensitive, i.e., there is no distiction between "keylabel":"value" and "Keylabel":"value" and "keyLabel":"value".)
By default keys in the JSON object that are associated with struct fields that have JSON tag "-" are ignored. If the "omitempty" attribute is included in the struct field tag they are by default also not included in the returned slice. IgnoreOmitemptyTag(false) can be called to override the handling of "omitempty" tags - this might be useful if you want to find the "omitempty" fields that are not set by decoding the JSON object.
If the struct has a member struct with `checkjson:"norecurse"` tag, then it is not scanned.
Example ¶
// struct to which we want to decode JSON object type test3 struct { Something string Else string } type test2 struct { Why string Not string Another test3 } type test struct { Ok bool Why string More test2 } tv := test{} data := []byte(`{"ok":true,"more":{"why":"again","another":{"else":"ok"}}}`) mems, err := MissingJSONKeys(data, tv) if err != nil { // handle error } fmt.Println("missing keys:", mems)
Output: missing keys: [Why More.Not More.Another.Something]
func ReadJSONFile ¶
ReadJSONFile returns an array of the JSON objects in 'file'. The file can have comments outside of the JSON objects as well as comments embedded in the JSON objects if preceeded by the number, '#', symbol.
File "test.json": This file contains some test data for ReadJSONFile ... { "author": "B. Dylan", "title" : "Ballad of a Thin Man" # one of my favorites } Code: j, _ := ReadJSONFile("test.json") fmt.Println(string(j[0])) // prints: {"author":"B. Dylan","title":"Ballad of a Thin Man"}
func ReadJSONReader ¶
ReadJSONReader returns the next JSON object from an io.Reader; it returns io.EOF if the Reader terminates. (See ReadJSONFile for notes on handling of embedded comments in JSON object.)
func ResolveJSONError ¶
ResolveJSONError tries to augment json.Unmarshal syntax errors with the JSON context - key:... - and position when parsing stopped, if possible. (This is useful when errors occur when unmarshaling large JSON objects.)
func SetKeysToIgnore ¶
func SetKeysToIgnore(s ...string)
SetKeysToIgnore maintains a list of JSON keys that should not be validated as exported struct fields. By default the JSON key "config" is not validated; it can be removed from the list by calling SetKeysToIgnore() with no arguments. The arguments are used as the list of keys to ignore and override the default. NOTE: keys are case insensitive - i.e., "key" == "Key" == "KEY".
A JSON object key that corresponds with a struct member that is defined with the JSON tag "-" will not be reported, since it is a valid key for the struct definiton, even if it won't be decoded by the Go stdlib.
Example ¶
// struct to which we want to decode JSON object type test2 struct { Maybe bool } type test struct { Ok bool Why test2 } tv := test{} data := []byte(`{"ok":true, "why":{"maybe":true,"maybenot":false}, "not":"I don't know"}`) SetKeysToIgnore("why.maybenot", "not") defer SetKeysToIgnore("") keys, err := UnknownJSONKeys(data, tv) if err != nil { // handle error } fmt.Println("unknown keys:", keys)
Output: unknown keys: []
func SetMembersToIgnore ¶
func SetMembersToIgnore(s ...string)
SetMembersToIgnore creates a list of exported struct field names that should not be checked for as keys in the JSON object. For hierarchical struct members provide the full path for the member name using dot-notation. Calling SetMembersToIgnore with no arguments - SetMembersToIgnore() - clears the list.
Example ¶
// struct to which we want to decode JSON object type test3 struct { Something string Else string } type test2 struct { Why string Not string Another test3 } type test struct { Ok bool Why string More test2 } data := []byte(`{"ok":true,"more":{"why":"again","another":{"else":"ok"}}}`) SetMembersToIgnore("why", "more.not", "more.another.something") defer SetMembersToIgnore() tv := test{} mems, err := MissingJSONKeys(data, tv) if err != nil { // handle error } fmt.Println("missing keys:", mems)
Output: missing keys: []
func UnknownJSONKeys ¶
UnknownJSONKeys returns a slice of the JSON object keys that will not be decoded to a member of 'val', which is of type struct. For nested JSON objects the keys are reported using dot-notation. (NOTE: JSON object keys and tags are treated as case insensitive, i.e., there is no distiction between "keylabel":"value" and "Keylabel":"value" and "keyLabel":"value".)
JSON object keys that may correspond with a struct member that is defined with the JSON tag "-" will not be included in the unknown key slice, since they are valid keys even though they won't be decoded by the Go stdlib.
NOTE: beginning with go v1.10, this is similar to setting (*Decoder)DisallowUnknownFields() for the stdlib json.Decoder; however, the stdlib stops and returns the first unknown key it encounters rather than a slice of all keys in the JSON object that will not be decoded. Also, the stdlib error message does not reference the unknown key with dot-notation; so if the error is deep in a JSON object it may be hard to locate. (NOTE: as of 3/5/19, change 145218, the stdlib now reports key using dot-notation, as here.)
Example ¶
// struct to which we want to decode JSON object type test2 struct { Maybe bool } type test struct { Ok bool Why test2 } tv := test{} data := []byte(`{"ok":true, "why":{"maybe":true,"maybenot":false}, "not":"I don't know"}`) defer SetKeysToIgnore("") keys, err := UnknownJSONKeys(data, tv) if err != nil { // handle error } fmt.Println("unknown keys:", keys)
Output: unknown keys: [why.maybenot not]
func Validate ¶
Validate scans a JSON object and returns an error when it encounters a key:value pair that will not decode to a member of the 'val' of type struct using the "encoding/json" package. (NOTE: JSON object keys and tags are treated as case insensitive, i.e., there is no distiction between "keylabel":"value" and "Keylabel":"value" and "keyLabel":"value".)
JSON object key that may correspond with a struct member that is defined with the JSON tag "-" will not be reported since it is a valid key even though it won't be decoded by the Go stdlib.
NOTE: result is similar to using (*Decoder)DisallowUnknownFields() in encoding/json lib; however, with Validate() error will provide route for for nested JSON object keys.
Types ¶
This section is empty.