SuperJSONOf

func SuperJSONOf(expectedJSON interface{}, params ...interface{}) TestDeep

SuperJSONOf operator allows to compare the JSON representation of data against expectedJSON. Unlike JSON operator, marshalled data must be a JSON object/map (aka {…}). expectedJSON can be a:

  • string containing JSON data like {"fullname":"Bob","age":42}
  • string containing a JSON filename, ending with “.json” (its content is ioutil.ReadFile before unmarshaling)
  • []byte containing JSON data
  • io.Reader stream containing JSON data (is ioutil.ReadAll before unmarshaling)

JSON data contained in expectedJSON must be a JSON object/map (aka {…}) too. During a match, each expected entry should match in the compared map. But some entries in the compared map may not be expected.

type MyStruct struct {
  Name string `json:"name"`
  Age  int    `json:"age"`
  City string `json:"city"`
}
got := MyStruct{
  Name: "Bob",
  Age:  42,
  City: "TestCity",
}
td.Cmp(t, got, td.SuperJSONOf(`{"name": "Bob", "age": 42}`))  // succeeds
td.Cmp(t, got, td.SuperJSONOf(`{"name": "Bob", "zip": 666}`)) // fails, miss "zip"

expectedJSON JSON value can contain placeholders. The params are for any placeholder parameters in expectedJSON. params can contain TestDeep operators as well as raw values. A placeholder can be numeric like $2 or named like $name and always references an item in params.

Numeric placeholders reference the n’th “operators” item (starting at 1). Named placeholders are used with Tag operator as follows:

td.Cmp(t, gotValue,
  SuperJSONOf(`{"fullname": $name, "age": $2, "gender": $3}`,
    td.Tag("name", td.HasPrefix("Foo")), // matches $1 and $name
    td.Between(41, 43),                  // matches only $2
    "male"))                             // matches only $3

Note that placeholders can be double-quoted as in:

td.Cmp(t, gotValue,
  td.SuperJSONOf(`{"fullname": "$name", "age": "$2", "gender": "$3"}`,
    td.Tag("name", td.HasPrefix("Foo")), // matches $1 and $name
    td.Between(41, 43),                  // matches only $2
    "male"))                             // matches only $3

It makes no difference whatever the underlying type of the replaced item is (= double quoting a placeholder matching a number is not a problem). It is just a matter of taste, double-quoting placeholders can be preferred when the JSON data has to conform to the JSON specification, like when used in a “.json” file.

Note expectedJSON can be a []byte, JSON filename or io.Reader:

td.Cmp(t, gotValue, td.SuperJSONOf("file.json", td.Between(12, 34)))
td.Cmp(t, gotValue, td.SuperJSONOf([]byte(`[1, $1, 3]`), td.Between(12, 34)))
td.Cmp(t, gotValue, td.SuperJSONOf(osFile, td.Between(12, 34)))

A JSON filename ends with “.json”.

To avoid a legit “$” string prefix causes a bad placeholder error, just double it to escape it. Note it is only needed when the “$” is the first character of a string:

td.Cmp(t, gotValue,
  td.SuperJSONOf(`{"fullname": "$name", "details": "$$info", "age": $2}`,
    td.Tag("name", td.HasPrefix("Foo")), // matches $1 and $name
    td.Between(41, 43)))                 // matches only $2

For the “details” key, the raw value “$info” is expected, no placeholders are involved here.

Note that Lax mode is automatically enabled by SuperJSONOf operator to simplify numeric tests.

Comments can be embedded in JSON data:

td.Cmp(t, gotValue,
  td.SuperJSONOf(`
{
  // A guy properties:
  "fullname": "$name",  // The full name of the guy
  "details":  "$$info", // Literally "$info", thanks to "$" escape
  "age":      $2        /* The age of the guy:
                           - placeholder unquoted, but could be without
                             any change
                           - to demonstrate a multi-lines comment */
}`,
    td.Tag("name", td.HasPrefix("Foo")), // matches $1 and $name
    td.Between(41, 43)))                 // matches only $2

Comments, like in go, have 2 forms. To quote the Go language specification:

  • line comments start with the character sequence // and stop at the end of the line.
  • multi-lines comments start with the character sequence /* and stop with the first subsequent character sequence */.

Last but not least, simple operators can be directly embedded in JSON data without requiring any placeholder but using directly $^OperatorName. They are operator shortcuts:

td.Cmp(t, gotValue, td.SuperJSONOf(`{"id": $1}`, td.NotZero()))

can be written as:

td.Cmp(t, gotValue, td.SuperJSONOf(`{"id": $^NotZero}`))

Unfortunately, only simple operators (in fact those which take no parameters) have shortcuts. They follow:

TypeBehind method returns the map[string]interface{} type.

See also SuperJSONOf godoc.

Examples

Basic example
Placeholders example
File example

CmpSuperJSONOf shortcut

func CmpSuperJSONOf(t TestingT, got interface{}, expectedJSON interface{}, params []interface{}, args ...interface{}) bool

CmpSuperJSONOf is a shortcut for:

td.Cmp(t, got, td.SuperJSONOf(expectedJSON, params...), args...)

See above for details.

Returns true if the test is OK, false if it fails.

args… are optional and allow to name the test. This name is used in case of failure to qualify the test. If len(args) > 1 and the first item of args is a string and contains a ‘%’ rune then fmt.Fprintf is used to compose the name, else args are passed to fmt.Fprint. Do not forget it is the name of the test, not the reason of a potential failure.

See also CmpSuperJSONOf godoc.

Examples

Basic example
Placeholders example
File example

T.SuperJSONOf shortcut

func (t *T) SuperJSONOf(got interface{}, expectedJSON interface{}, params []interface{}, args ...interface{}) bool

SuperJSONOf is a shortcut for:

t.Cmp(got, td.SuperJSONOf(expectedJSON, params...), args...)

See above for details.

Returns true if the test is OK, false if it fails.

args… are optional and allow to name the test. This name is used in case of failure to qualify the test. If len(args) > 1 and the first item of args is a string and contains a ‘%’ rune then fmt.Fprintf is used to compose the name, else args are passed to fmt.Fprint. Do not forget it is the name of the test, not the reason of a potential failure.

See also T.SuperJSONOf godoc.

Examples

Basic example
Placeholders example
File example