Files
substrate/vendor/github.com/go-openapi/swag/jsonutils
Tim Hockin a8d83ee1b5 Use Kubernetes declarative validation (#1215)
This mostly eliminates the need to hand-write validation code.

This PR is a long series of commits which add DV for most of Actor and
all of Atespace.

Here is a map to the commits:
* The first few take a dep on a new Kubernetes tag, import the code into
third_party, and apply a single patch. Because we have different Go
modules for tools, I had to do it twice. When that patch lands, we can
revert these commits, but that won't be until the 1.38 cycle in a few
months.
* The next commits slowly add DV support, so a human can review each of
them in a reasonable amount of time. The emphasis is on great test
cases.
* I made a bad choice early on as to where to generate the code into, so
I moved it. Rebasing on that was exceedingly hard, so I left it as a
move.
* This required changing update/go-generate -> update/codegen -- we need
to get the ordering of tools right, which `go generate` does not
guarantee.
* Then I added a "middle" layer called "ServiceImpl" between the RPC and
storage layers. This allows things like workflow to call the same
business logic as the RPC layer, including validation. Lots of test
fixes.
* Then I finished the Create() and Update() paths for Actor. Those
represent the "right" (or closest to) way to implement resources, and
tests for validation.

I strongly encourage reviewers to read it commit-by-commit. Rebasing
this is VERY tedious, so the sooner it lands or dies completely, the
better. Then we can start converting the rest.

`./hack/run-tool.sh validation-gen --docs` will produce some docs on the
tool and the available tags.

@laoj2 @juli4n @EItanya @HavenXia
@lalitc375 @yongruilin @jpbetz  FYI
2026-08-25 20:24:59 -07:00
..
2026-06-02 20:02:51 -07:00
2026-06-02 20:02:51 -07:00
2026-06-02 20:02:51 -07:00
2026-06-02 20:02:51 -07:00

jsonutils

jsonutils exposes a few tools to work with JSON:

  • a fast, simple Concat to concatenate (not merge) JSON objects and arrays
  • FromDynamicJSON to convert a data structure into a "dynamic JSON" data structure
  • ReadJSON and WriteJSON behave like json.Unmarshal and json.Marshal, with the ability to use another underlying serialization library through an Adapter configured at runtime
  • a JSONMapSlice structure that may be used to store JSON objects with the order of keys maintained

Dynamic JSON

We call "dynamic JSON" the go data structure that results from unmarshaling JSON like this:

  var value any
  jsonBytes := `{"a": 1, ... }`
  _ = json.Unmarshal(jsonBytes, &value)

In this configuration, the standard library mappings are as follows:

JSON go
number float64
string string
boolean bool
null nil
object map[string]any
array []any

Map slices

When using JSONMapSlice, the ordering of keys is ensured by replacing mappings to map[string]any by a JSONMapSlice which is an (ordered) slice of JSONMapItems.

Notice that a similar feature is available for YAML (see yamlutils), with a YAMLMapSlice type based on the JSONMapSlice.

JSONMapSlice is similar to an ordered map, but the keys are not retrieved in constant time.

Another difference with the the above standard mappings is that numbers don't always map to a float64: if the value is a JSON integer, it unmarshals to int64.

See also some examples

Adapters

ReadJSON, WriteJSON and FromDynamicJSON (which is a combination of the latter two) are wrappers on top of json.Unmarshal and json.Marshal.

By default, the adapter merely wraps the standard library.

The adapter may be used to register other JSON serialization libraries, possibly several ones at the same time.

If the value passed is identified as an "ordered map" (i.e. implements ifaces.Ordered or ifaces.SetOrdered, the adapter favors the "ordered" JSON behavior and tries to find a registered implementation that support ordered keys in objects.

Our standard library implementation supports this.

As of v0.25.0, we support through such an adapter the popular mailru/easyjson library, which kicks in when the passed values support the easyjson.Unmarshaler or easyjson.Marshaler interfaces.

In the future, we plan to add more similar libraries that compete on the go JSON serializers scene.

Registering an adapter

In package github.com/go-openapi/swag/easyjson/adapters, several adapters are available.

Each adapter is an independent go module. Hence you'll pick its dependencies only if you import it.

At this moment we provide:

  • stdlib: JSON adapter based on the standard library
  • easyjson: JSON adapter based on the github.com/mailru/easyjson

The adapters provide the basic Marshal and Unmarshal capabilities, plus an implementation of the MapSlice pattern.

You may also build your own adapter based on your specific use-case. An adapter is not required to implement all capabilities.

Every adapter comes with a Register function, possibly with some options, to register the adapter to a global registry.

For example, to enable easyjson to be used in ReadJSON and WriteJSON, you would write something like:

  import (
	  "github.com/go-openapi/swag/jsonutils/adapters"
	  easyjson "github.com/go-openapi/swag/jsonutils/adapters/easyjson/json"
  )

  func init() {
	  easyjson.Register(adapters.Registry)
  }

You may register several adapters. In this case, capability matching is evaluated from the last registered adapters (LIFO).

Benchmarks