Flexible types[1] for un-marshaling any JSON[2] value.
This lib is useful when API clients send inconsistent JSON.
For example, a webhook endpoint might want to accept POST requests with body:
- This is what the API expects
{
"sku": "123",
"price": 9.99
}
- This will also un-marshal, sku is cast to a string, and price to a float64. Errors if price is not a valid number
{
"sku": 123,
"price": "9.99"
}
Validation can then be done after un-marshaling
This package builds on
null.*
types in guregu/nullsql.Null*
types in database/sql
Numeric types (Int, Float) wrap 64bit base types, e.g. int64 and float64.
For each basic type, this package implements two flexible types[3], for example
- required struct fields may use ft.String, it supports flexible types when un-marshaling.
- optional fields may use ft.NString, it supports both flexible types and allows NULL. Think of the N-prefix as meaning "allows null", or "not-required"
type Data struct {
Required ft.String `json:"required"`
Optional ft.NString `json:"optional"`
}
The data type above can be used to un-marshal the following JSON
{
"required": 123,
"optional": null
}
NULL is not considered valid, for example
b := []byte(`{"required": 123,"optional": null}`)
d := Data{}
err := json.Unmarshal(b, &d)
// ft.String doesn't have the Valid property
fmt.Println(d.Required.String) // "123"
fmt.Println(d.Optional.Valid) // false
fmt.Println(d.Optional.String) // ""
Valid is set if the value is defined (not null), don't use it for e.g. form validation. Rather create a method on the data type
// Valid validates all the required properties in the Data type
func (d *Data) Valid() bool {
return d.Required.String == "123"
}
Flexible types can be used with the templating packages. The data type above could be used like this
t1 := template.Must(template.New("t1").Parse(
`{{if not .Optional.Valid }}Required = {{.Required.String}} {{end}}`))
t1.Execute(os.Stdout, d) // Required = 123
See tests for more usage examples
git clone https://github.com/mozey/ft.git && cd ft
go clean -testcache && go test -v ./...
Not quite the same concept as Flexible typing in SQLite. Note that "as of SQLite version 3.37.0 (2021-11-27), SQLite supports this development style [Rigid Type Enforcement] using STRICT tables"
Previously this repo used the term "fuzzy types". It was renamed, and the term replaced with "flexible types". To avoid confusion with fuzzing, a new feature added to the "standard toolchain beginning in Go 1.18"
This repo does not use generics, and will compile with older versions of Go