Skip to content

Commit d2fce25

Browse files
author
Jamie Tanna
committed
Implement oapi-codegen/nullable
This bootstraps a new repository for the `oapi-codegen` organisation's standards, and then implements the `Nullable` type as per [0] and [1]. Using a `map` as the underlying type allows us to take advantage of `json.Marshal`'s inbuilt checks to determine whether to `omitempty` a JSON value, which isn't possible with a `struct`. We can make sure this is a multi-module project, similar to other projects, so we can isolate test-only dependencies from the core project, which has zero dependencies. We can also add convenience helpers for `NewNullableWithValue` and `NewNullNullable` as they can be useful when constructing `struct`s in tests. In the top-level project we can use runnable examples to indicate the example usage and cover all the test cases we need, and then use the `internal/test` package to perform further checks. Co-authored-by: Sebastien Guilloux <sebastien.guilloux@elastic.co> Co-authored-by: Ashutosh Kumar <ashutosh.kumar@elastic.co> [0]: golang/go#64515 (comment) [1]: https://github.com/sebgl/nullable/
0 parents  commit d2fce25

File tree

16 files changed

+813
-0
lines changed

16 files changed

+813
-0
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* @oapi-codegen/maintainers

.github/release-drafter.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
_extends: .github

.github/workflows/ci.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: Build project
2+
on: [ push, pull_request ]
3+
jobs:
4+
build:
5+
name: Build
6+
runs-on: ubuntu-latest
7+
strategy:
8+
fail-fast: false
9+
# perform matrix testing to give us an earlier insight into issues with different versions of supported major versions of Go
10+
matrix:
11+
version:
12+
- "1.20"
13+
- "1.21"
14+
steps:
15+
- name: Check out source code
16+
uses: actions/checkout@v4
17+
18+
- name: Set up Go
19+
uses: actions/setup-go@v5
20+
with:
21+
go-version: ${{ matrix.version }}
22+
23+
- name: Test
24+
run: make test

.github/workflows/lint.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: Lint project
2+
on: [push, pull_request]
3+
jobs:
4+
build:
5+
name: Build
6+
runs-on: ubuntu-latest
7+
strategy:
8+
fail-fast: false
9+
# perform matrix testing to give us an earlier insight into issues with different versions of supported major versions of Go
10+
matrix:
11+
version:
12+
- "1.20"
13+
- "1.21"
14+
steps:
15+
- name: Check out source code
16+
uses: actions/checkout@v4
17+
18+
- name: Set up Go
19+
uses: actions/setup-go@v5
20+
with:
21+
go-version: ${{ matrix.version }}
22+
23+
- name: Run `make lint-ci`
24+
run: make lint-ci
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Release Drafter
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
workflow_dispatch: {}
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
update_release_draft:
14+
permissions:
15+
contents: write
16+
pull-requests: write
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: release-drafter/release-drafter@v5
20+
with:
21+
name: next
22+
tag: next
23+
version: next
24+
env:
25+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/tidy.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Ensure `go mod tidy` has been run
2+
on: [ push, pull_request ]
3+
jobs:
4+
build:
5+
name: Build
6+
runs-on: ubuntu-latest
7+
strategy:
8+
fail-fast: false
9+
# perform matrix testing to give us an earlier insight into issues with different versions of supported major versions of Go
10+
matrix:
11+
version:
12+
- "1.20"
13+
- "1.21"
14+
steps:
15+
- name: Check out source code
16+
uses: actions/checkout@v4
17+
18+
- name: Set up Go
19+
uses: actions/setup-go@v5
20+
with:
21+
go-version: ${{ matrix.version }}
22+
23+
- name: Install `tidied`
24+
run: go install gitlab.com/jamietanna/tidied@latest
25+
26+
- name: Check for no untracked files
27+
run: tidied -verbose

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/bin

LICENSE

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Copyright 2024 oapi-codegen
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.

Makefile

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
GOBASE=$(shell pwd)
2+
GOBIN=$(GOBASE)/bin
3+
4+
help:
5+
@echo "This is a helper makefile for oapi-codegen"
6+
@echo "Targets:"
7+
@echo " test: run all tests"
8+
@echo " tidy tidy go mod"
9+
@echo " lint run linting"
10+
11+
$(GOBIN)/golangci-lint:
12+
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOBIN) v1.55.2
13+
14+
.PHONY: tools
15+
tools: $(GOBIN)/golangci-lint
16+
17+
lint: tools
18+
git ls-files go.mod '**/*go.mod' -z | xargs -0 -I{} bash -xc 'cd $$(dirname {}) && $(GOBIN)/golangci-lint run ./...'
19+
20+
lint-ci: tools
21+
git ls-files go.mod '**/*go.mod' -z | xargs -0 -I{} bash -xc 'cd $$(dirname {}) && $(GOBIN)/golangci-lint run ./... --out-format=github-actions --timeout=5m'
22+
23+
test:
24+
git ls-files go.mod '**/*go.mod' -z | xargs -0 -I{} bash -xc 'cd $$(dirname {}) && go test -cover ./...'
25+
26+
tidy:
27+
@echo "tidy..."
28+
git ls-files go.mod '**/*go.mod' -z | xargs -0 -I{} bash -xc 'cd $$(dirname {}) && go mod tidy'

README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# oapi-codegen/nullable
2+
3+
> An implementation of a `Nullable` type for JSON bodies, indicating whether the field is absent, set to null, or set to a value
4+
5+
Unlike other known implementations, this makes it possible to both marshal and unmarshal the value, as well as represent all three states:
6+
7+
- the field is _not set_
8+
- the field is _explicitly set to null_
9+
- the field is _explicitly set to a given value_
10+
11+
And can be embedded in structs, for instance with the following definition:
12+
13+
```go
14+
obj := struct {
15+
// RequiredID is a required, nullable field
16+
RequiredID nullable.Nullable[int] `json:"id"`
17+
// RequiredID is an optional, nullable field
18+
OptionalString *nullable.Nullable[string] `json:"optionalString,omitempty"`
19+
}{}
20+
```
21+
22+
## Usage
23+
24+
> [!IMPORTANT]
25+
> Although this project is under the [oapi-codegen org](https://github.com/oapi-codegen) for the `oapi-codegen` OpenAPI-to-Go code generator, this is intentionally released as a separate, standalone library which can be used by other projects.
26+
27+
First, add to your project with:
28+
29+
```sh
30+
go get github.com/oapi-codegen/nullable
31+
```
32+
33+
Check out the examples in [the package documentation on pkg.go.dev](https://pkg.go.dev/github.com/oapi-codegen/nullable) for more details.
34+
35+
## Credits
36+
37+
- [KumanekoSakura](https://github.com/KumanekoSakura), [via](https://github.com/golang/go/issues/64515#issuecomment-1841057182)
38+
- [Sebastien Guilloux], [via](https://github.com/sebgl/nullable/)
39+
40+
As well as contributions from:
41+
42+
- [Jamie Tanna](https://www.jvt.me)
43+
- [Ashutosh Kumar](https://github.com/sonasingh46)
44+
45+
## License
46+
47+
Licensed under the Apache-2.0 license.

0 commit comments

Comments
 (0)