# Swag [![Build Status](https://github.com/go-openapi/swag/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/swag/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/swag/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/swag) [![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io) [![license](https://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/swag/master/LICENSE) [![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/swag.svg)](https://pkg.go.dev/github.com/go-openapi/swag) [![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/swag)](https://goreportcard.com/report/github.com/go-openapi/swag) 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 in `github.com/go-openapi/...` depend on it in some way. > And so does our CLI tool `github.com/go-swagger/go-swagger`, > as well as the code generated by this tool. * [Contents](#contents) * [Dependencies](#dependencies) * [Release Notes](#release-notes) * [Licensing](#licensing) * [Note to contributors](#note-to-contributors) * [TODOs, suggestions and plans](#todos-suggestions-and-plans) ## Contents `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 structures
~require `github.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`
~require `github.com/mailru/easyjson`~
require `go.yaml.in/yaml/v3`
| --- ## Dependencies 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 module `github.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` ## Release notes ### v0.25.4 ** mangling** Bug fix * [x] mangler may panic with pluralized overlapping initialisms Tests * [x] introduced fuzz tests ### v0.25.3 ** mangling** Bug fix * [x] mangler may panic with pluralized initialisms ### v0.25.2 Minor changes due to internal maintenance that don't affect the behavior of the library. * [x] removed indirect test dependencies by switching all tests to `go-openapi/testify`, a fork of `stretch/testify` with zero-dependencies. * [x] improvements to CI to catch test reports. * [x] modernized licensing annotations in source code, using the more compact SPDX annotations rather than the full license terms. * [x] simplified a bit JSON & YAML testing by using newly available assertions * started the journey to an OpenSSF score card badge: * [x] explicited permissions in CI workflows * [x] published security policy * pinned dependencies to github actions * introduced fuzzing in tests ### v0.25.1 * fixes a data race that could occur when using the standard library implementation of a JSON ordered map ### v0.25.0 **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 preferred 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 standard `encoding/json` is provided. * an independent [benchmark](./jsonutils/adapters/testintegration/benchmarks/README.md) to compare the different adapters * improves the "float is integer" check (`conv.IsFloat64AJSONInteger`) (#59) * removes the _direct_ dependency to `gopkg.in/yaml.v3` (indirect dependency is still incurred through `stretchr/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`, for `go1.25` builds. * provide similar implementations for `goccy/go-json` and `jsoniterator/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`. ```go import ( "github.com/go-openapi/swag/jsonutils/adapters" easyjson "github.com/go-openapi/swag/jsonutils/adapters/easyjson/json" ) func init() { easyjson.Register(adapters.Registry) } ``` 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. For more details, you may also look at our [integration tests](jsonutils/adapters/testintegration/integration_suite_test.go#29). ### v0.24.0 With this release, we have largely modernized the API of `swag`: * The traditional `swag` API is still supported: code that imports `swag` 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**: * [x] type converters and pointer to value helpers now support generic types * [x] 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. * [x] performance: small improvements to reduce the overhead of convert/format wrappers (see issues #110, or PR #108) * [x] performance: name mangling utilities run ~ 10% faster (PR #115) --- ## Licensing This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE). ## Note to contributors 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 a `go 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 by `go mod` and `go 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` vs `v0.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. ## Todos, suggestions and plans All kinds of contributions are welcome. A few ideas: * [x] Complete the split of dependencies to isolate easyjson from the rest * [x] Improve CI to reduce needed tests * [x] 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 new `swag` 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)