Package swag
contains a bunch of helper functions for go-openapi and go-swagger projects.
You may also use it standalone for your projects.
NOTE
swag
is one of the foundational building blocks of the go-openapi initiative. Most repositories ingithub.com/go-openapi/...
depend on it in some way. And so does our CLI toolgithub.com/go-swagger/go-swagger
, as well as the code generated by this tool.
go-openapi/swag
exposes a collection of relatively independent modules.
Moving forward, no additional feature will be added to the swag
API directly at the root package level,
which remains there for backward-compatibility purposes. All exported top-level features are now deprecated.
Child modules will continue to evolve and some new ones may be added in the future.
Module | Content | Main features |
---|---|---|
cmdutils |
utilities to work with CLIs | |
conv |
type conversion utilities | convert between values and pointers for any types convert from string to builtin types (wraps strconv )require ./typeutils (test dependency) |
fileutils |
file utilities | |
jsonname |
JSON utilities | infer JSON names from go properties |
jsonutils |
JSON utilities | fast json concatenation read and write JSON from and to dynamic go data structuresgithub.com/mailru/easyjson |
loading |
file loading | load from file or http require ./yamlutils |
mangling |
safe name generation | name mangling for go |
netutils |
networking utilities | host, port from address |
stringutils |
string utilities |
search in slice (with case-insensitive) split/join query parameters as arrays |
typeutils |
go types utilities |
check the zero value for any type safe check for a nil value |
yamlutils |
YAML utilities | converting YAML to JSON loading YAML into a dynamic YAML document maintaining the original order of keys in YAML objects require ./jsonutils github.com/mailru/easyjson require go.yaml.in/yaml/v3 |
The root module github.com/go-openapi/swag
at the repo level maintains a few
dependencies outside of the standard library.
- YAML utilities depend on
go.yaml.in/yaml/v3
- JSON utilities depend on their registered adapter module:
- by default, only the standard library is used
github.com/mailru/easyjson
is now only a dependency for modulegithub.com/go-openapi/swag/jsonutils/adapters/easyjson/json
, for users willing to import that module.- integration tests and benchmarks use all the dependencies are published as their own module
- other dependencies are test dependencies drawn from
github.com/stretchr/testify
- fixes a data race that could occur when using the standard library implementation of a JSON ordered map
New with this release:
- requires
go1.24
, as iterators are being introduced - removes the dependency to
mailru/easyjson
by default (#68)- functionality remains the same, but performance may somewhat degrade for applications
that relied on
easyjson
- users of the JSON or YAML utilities who want to use
easyjson
as their prefered JSON serializer library will be able to do so by registering this the corresponding JSON adapter at runtime. See below. - ordered keys in JSON and YAML objects: this feature used to rely solely on
easyjson
. With this release, an implementation relying on the standardencoding/json
is provided. - an independent benchmark to compare the different adapters
- functionality remains the same, but performance may somewhat degrade for applications
that relied on
- improves the "float is integer" check (
conv.IsFloat64AJSONInteger
) (#59) - removes the direct dependency to
gopkg.in/yaml.v3
(indirect dependency is still incurred throughstretchr/testify
) (#127) - exposed
conv.IsNil()
(previously kept private): a safe nil check (accounting for the "non-nil interface with nil value" nonsensical go trick)
What coming next?
Moving forward, we want to :
- provide an implementation of the JSON adapter based on
encoding/json/v2
, forgo1.25
builds. - provide similar implementations for
goccy/go-json
andjsoniterator/go
, and perhaps some other similar libraries may be interesting too.
How to explicitly register a dependency at runtime?
The following would maintain how JSON utilities proposed by swag
used work, up to v0.24.1
.
import "github.com/go-openapi/swag/jsonutils/adapters/easyjson/json"
func init() {
json.Register()
}
Subsequent calls to jsonutils.ReadJSON()
or jsonutils.WriteJSON()
will switch to easyjson
whenever the passed data structures implement the easyjson.Unmarshaler
or easyjson.Marshaler
respectively,
or fallback to the standard library.
With this release, we have largely modernized the API of swag
:
- The traditional
swag
API is still supported: code that importsswag
will still compile and work the same. - A deprecation notice is published to encourage consumers of this library to adopt the newer API
- Deprecation notice
- configuration through global variables is now deprecated, in favor of options passed as parameters
- all helper functions are moved to more specialized packages, which are exposed as go modules. Importing such a module would reduce the footprint of dependencies.
- all functions, variables, constants exposed by the deprecated API have now moved, so that consumers of the new API no longer need to import github.com/go-openapi/swag, but should import the desired sub-module(s).
New with this release:
- type converters and pointer to value helpers now support generic types
- name mangling now support pluralized initialisms (issue #46) Strings like "contact IDs" are now recognized as such a plural form and mangled as a linter would expect.
- performance: small improvements to reduce the overhead of convert/format wrappers (see issues #110, or PR #108)
- performance: name mangling utilities run ~ 10% faster (PR #115)
A mono-repo structure comes with some unavoidable extra pains...
- Testing
The usual
go test ./...
command, run from the root of this repo won't work any longer to test all submodules.Each module constitutes an independant unit of test. So you have to run
go test
inside each module. Or you may take a look at how this is achieved by CI [here] https://github.com/go-openapi/swag/blob/master/.github/workflows/go-test.yml).There are also some alternative tricks using
go work
, for local development, if you feel comfortable with go workspaces. Perhaps some day, we'll have ago work test
to run all tests without any hack.
- Releasing
Each module follows its own independant module versioning.
So you have tags like
mangling/v0.24.0
,fileutils/v0.24.0
etc that are used bygo mod
andgo get
to refer to the tagged version of each module specifically.This means we may release patches etc to each module independently.
We'd like to adopt the rule that modules in this repo would only differ by a patch version (e.g.
v0.24.5
vsv0.24.3
), and we'll level all modules whenever a minor version is introduced.A script in
./hack
is provided to tag all modules with the same version in one go.
- Continuous integration
At this moment, all tests in all modules are systematically run over the full test matrix (3 platform x 2 go releases). This generates quite a lot of jobs.
We ought to reduce the number of jobs required to test a PR focused on only a few modules.
All kinds of contributions are welcome.
A few ideas:
- Complete the split of dependencies to isolate easyjson from the rest
- Improve CI to reduce needed tests
- Replace dependency to
gopkg.in/yaml.v3
(yamlutil
) - Improve mangling utilities (improve readability, support for capitalized words, better word substitution for non-letter symbols...)
- Move back to this common shared pot a few of the technical features introduced by go-swagger independently (e.g. mangle go package names, search package with go modules support, ...)
- Apply a similar mono-repo approach to go-openapi/strfmt which suffer from similar woes: bloated API, imposed dependency to some database driver.
- Adapt
go-swagger
(incl. generated code) to the newswag
API. - Factorize some tests, as there is a lot of redundant testing code in
jsonutils
- Benchmark & profiling: publish independently the tool built to analyze and chart benchmarks (e.g. similar to
benchvisual
) - more thorough testing for nil / null case
- ci pipeline to manage releases
- cleaner mockery generation (doesn't work out of the box for all sub-modules)