GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Why Go
  • Case Studies
  • Use Cases
  • Security
  • Learn
  • Effective Go
  • Go User Manual
  • Standard library
  • Release Notes
  • API
  • Packages
  • Recorded Talks
  • Meetups
  • Conferences

This view

  • Original page
  • New address

GeezerVison is showing pkg.go.dev — nullable package - github.com/oapi-codegen/nullable - Go Packages

Details

  • checked Valid go.mod file

    The Go module system was introduced in Go 1.11 and is the official dependency management solution for Go.

  • checked Redistributable license

    Redistributable licenses place minimal restrictions on how software can be used, modified, and redistributed.

  • checked Tagged version

    Modules with tagged versions give importers more predictable builds.

  • checked Stable version

    When a project reaches major version v1 it is considered stable.

  • Learn more about best practices

Repository

github.com/oapi-codegen/nullable

Links

  • Open Source Insights Logo Open Source Insights

README ¶

oapi-codegen/nullable

An implementation of a Nullable type for JSON bodies, indicating whether the field is absent, set to null, or set to a value

Unlike other known implementations, this makes it possible to both marshal and unmarshal the value, as well as represent all three states:

  • the field is not set
  • the field is explicitly set to null
  • the field is explicitly set to a given value

And can be embedded in structs, for instance with the following definition:

obj := struct {
		// RequiredID is a required, nullable field
		RequiredID     nullable.Nullable[int]     `json:"id"`
		// OptionalString is an optional, nullable field
		// NOTE that no pointer is required, only `omitempty`
		OptionalString nullable.Nullable[string] `json:"optionalString,omitempty"`
}{}

Usage

[!IMPORTANT] Although this project is under the oapi-codegen org 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.

First, add to your project with:

go get github.com/oapi-codegen/nullable

Check out the examples in the package documentation on pkg.go.dev for more details.

Credits

  • KumanekoSakura, via
  • Sebastien Guilloux, via

As well as contributions from:

  • Jamie Tanna
  • Ashutosh Kumar

License

Licensed under the Apache-2.0 license.

Documentation ¶

Index ¶

  • type Nullable
    • func NewNullNullable[T any]() Nullable[T]
    • func NewNullableWithValue[T any](t T) Nullable[T]
    • func (t Nullable[T]) Get() (T, error)
    • func (t Nullable[T]) GetOrEmpty() T
    • func (t Nullable[T]) IsNull() bool
    • func (t Nullable[T]) IsSpecified() bool
    • func (t Nullable[T]) MarshalJSON() ([]byte, error)
    • func (t Nullable[T]) MustGet() T
    • func (t *Nullable[T]) Set(value T)
    • func (t *Nullable[T]) SetNull()
    • func (t *Nullable[T]) SetUnspecified()
    • func (t *Nullable[T]) UnmarshalJSON(data []byte) error

Examples ¶

  • NewNullNullable
  • NewNullableWithValue
  • Nullable (MarshalOptional)
  • Nullable (MarshalRequired)
  • Nullable (UnmarshalOptional)
  • Nullable (UnmarshalRequired)

Constants ¶

This section is empty.

Variables ¶

This section is empty.

Functions ¶

This section is empty.

Types ¶

type Nullable ¶

type Nullable[T any] map[bool]T

Nullable is a generic type, which implements a field that can be one of three states:

- field is not set in the request - field is explicitly set to `null` in the request - field is explicitly set to a valid value in the request

Nullable is intended to be used with JSON marshalling and unmarshalling.

Internal implementation details:

- map[true]T means a value was provided - map[false]T means an explicit null was provided - nil or zero map means the field was not provided

If the field is expected to be optional, add the `omitempty` JSON tags. Do NOT use `*Nullable`!

Adapted from https://github.com/golang/go/issues/64515#issuecomment-1841057182

Example (MarshalOptional) ¶
package main

import (
	"encoding/json"
	"fmt"

	"github.com/oapi-codegen/nullable"
)

func main() {
	obj := struct {
		ID nullable.Nullable[int] `json:"id,omitempty"`
	}{}

	// when it's not set (by default)
	b, err := json.Marshal(obj)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Println("Unspecified:")
	fmt.Printf(`JSON: %s`+"\n", b)
	fmt.Println("---")

	// when it's not set (explicitly)
	obj.ID.SetUnspecified()

	b, err = json.Marshal(obj)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Println("Unspecified:")
	fmt.Printf(`JSON: %s`+"\n", b)
	fmt.Println("---")

	// when it's set explicitly to nil
	obj.ID.SetNull()

	b, err = json.Marshal(obj)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Println("Null:")
	fmt.Printf(`JSON: %s`+"\n", b)
	fmt.Println("---")

	// when it's set explicitly to the zero value
	var v int
	obj.ID.Set(v)

	b, err = json.Marshal(obj)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Println("Zero value:")
	fmt.Printf(`JSON: %s`+"\n", b)
	fmt.Println("---")

	// when it's set explicitly to a specific value
	v = 12345
	obj.ID.Set(v)

	b, err = json.Marshal(obj)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Println("Value:")
	fmt.Printf(`JSON: %s`+"\n", b)
	fmt.Println("---")

}
Output:
Unspecified:
JSON: {}
---
Unspecified:
JSON: {}
---
Null:
JSON: {"id":null}
---
Zero value:
JSON: {"id":0}
---
Value:
JSON: {"id":12345}
---

Example (MarshalRequired) ¶
package main

import (
	"encoding/json"
	"fmt"

	"github.com/oapi-codegen/nullable"
)

func main() {
	obj := struct {
		ID nullable.Nullable[int] `json:"id"`
	}{}

	// when it's not set (by default)
	b, err := json.Marshal(obj)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Println("Unspecified:")
	fmt.Printf(`JSON: %s`+"\n", b)
	fmt.Println("---")

	// when it's not set (explicitly)
	obj.ID.SetUnspecified()

	b, err = json.Marshal(obj)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Println("Unspecified:")
	fmt.Printf(`JSON: %s`+"\n", b)
	fmt.Println("---")

	// when it's set explicitly to nil
	obj.ID.SetNull()

	b, err = json.Marshal(obj)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Println("Null:")
	fmt.Printf(`JSON: %s`+"\n", b)
	fmt.Println("---")

	// when it's set explicitly to the zero value
	var v int
	obj.ID.Set(v)

	b, err = json.Marshal(obj)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Println("Zero value:")
	fmt.Printf(`JSON: %s`+"\n", b)
	fmt.Println("---")

	// when it's set explicitly to a specific value
	v = 12345
	obj.ID.Set(v)

	b, err = json.Marshal(obj)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Println("Value:")
	fmt.Printf(`JSON: %s`+"\n", b)
	fmt.Println("---")

}
Output:
Unspecified:
JSON: {"id":0}
---
Unspecified:
JSON: {"id":0}
---
Null:
JSON: {"id":null}
---
Zero value:
JSON: {"id":0}
---
Value:
JSON: {"id":12345}
---

Example (UnmarshalOptional) ¶
package main

import (
	"encoding/json"
	"fmt"

	"github.com/oapi-codegen/nullable"
)

func main() {
	obj := struct {
		// Note that there is no pointer for nullable.Nullable when it's
		Name nullable.Nullable[string] `json:"name,omitempty"`
	}{}

	// when it's not set
	err := json.Unmarshal([]byte(`
		{
		}
		`), &obj)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Println("Unspecified:")
	fmt.Printf("obj.Name.IsSpecified(): %v\n", obj.Name.IsSpecified())
	fmt.Printf("obj.Name.IsNull(): %v\n", obj.Name.IsNull())
	fmt.Println("---")

	// when it's set explicitly to nil
	err = json.Unmarshal([]byte(`
		{
		"name": null
		}
		`), &obj)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Println("Null:")
	fmt.Printf("obj.Name.IsSpecified(): %v\n", obj.Name.IsSpecified())
	fmt.Printf("obj.Name.IsNull(): %v\n", obj.Name.IsNull())
	fmt.Println("---")

	// when it's set explicitly to the zero value
	err = json.Unmarshal([]byte(`
		{
		"name": ""
		}
		`), &obj)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Println("Zero value:")
	fmt.Printf("obj.Name.IsSpecified(): %v\n", obj.Name.IsSpecified())
	fmt.Printf("obj.Name.IsNull(): %v\n", obj.Name.IsNull())
	val, err := obj.Name.Get()
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Printf("obj.Name.Get(): %#v <nil>\n", val)
	fmt.Printf("obj.Name.GetOrEmpty(): %#v\n", obj.Name.GetOrEmpty())
	fmt.Printf("obj.Name.MustGet(): %#v\n", obj.Name.MustGet())
	fmt.Println("---")

	// when it's set explicitly to a specific value
	err = json.Unmarshal([]byte(`
		{
		"name": "foo"
		}
		`), &obj)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	fmt.Println("Value:")
	fmt.Printf("obj.Name.IsSpecified(): %v\n", obj.Name.IsSpecified())
	fmt.Printf("obj.Name.IsNull(): %v\n", obj.Name.IsNull())
	val, err = obj.Name.Get()
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Printf("obj.Name.Get(): %#v <nil>\n", val)
	fmt.Printf("obj.Name.GetOrEmpty(): %#v\n", obj.Name.GetOrEmpty())
	fmt.Printf("obj.Name.MustGet(): %#v\n", obj.Name.MustGet())
	fmt.Println("---")

}
Output:
Unspecified:
obj.Name.IsSpecified(): false
obj.Name.IsNull(): false
---
Null:
obj.Name.IsSpecified(): true
obj.Name.IsNull(): true
---
Zero value:
obj.Name.IsSpecified(): true
obj.Name.IsNull(): false
obj.Name.Get(): "" <nil>
obj.Name.GetOrEmpty(): ""
obj.Name.MustGet(): ""
---
Value:
obj.Name.IsSpecified(): true
obj.Name.IsNull(): false
obj.Name.Get(): "foo" <nil>
obj.Name.GetOrEmpty(): "foo"
obj.Name.MustGet(): "foo"
---

Example (UnmarshalRequired) ¶
package main

import (
	"encoding/json"
	"fmt"

	"github.com/oapi-codegen/nullable"
)

func main() {
	obj := struct {
		Name nullable.Nullable[string] `json:"name"`
	}{}

	// when it's not set
	err := json.Unmarshal([]byte(`
		{
		}
		`), &obj)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Println("Unspecified:")
	fmt.Printf("obj.Name.IsSpecified(): %v\n", obj.Name.IsSpecified())
	fmt.Printf("obj.Name.IsNull(): %v\n", obj.Name.IsNull())
	fmt.Println("---")

	// when it's set explicitly to nil
	err = json.Unmarshal([]byte(`
		{
		"name": null
		}
		`), &obj)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Println("Null:")
	fmt.Printf("obj.Name.IsSpecified(): %v\n", obj.Name.IsSpecified())
	fmt.Printf("obj.Name.IsNull(): %v\n", obj.Name.IsNull())
	fmt.Println("---")

	// when it's set explicitly to the zero value
	err = json.Unmarshal([]byte(`
		{
		"name": ""
		}
		`), &obj)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Println("Zero value:")
	fmt.Printf("obj.Name.IsSpecified(): %v\n", obj.Name.IsSpecified())
	fmt.Printf("obj.Name.IsNull(): %v\n", obj.Name.IsNull())
	val, err := obj.Name.Get()
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Printf("obj.Name.Get(): %#v <nil>\n", val)
	fmt.Printf("obj.Name.GetOrEmpty(): %#v\n", obj.Name.GetOrEmpty())
	fmt.Printf("obj.Name.MustGet(): %#v\n", obj.Name.MustGet())
	fmt.Println("---")

	// when it's set explicitly to a specific value
	err = json.Unmarshal([]byte(`
		{
		"name": "foo"
		}
		`), &obj)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	fmt.Println("Value:")
	fmt.Printf("obj.Name.IsSpecified(): %v\n", obj.Name.IsSpecified())
	fmt.Printf("obj.Name.IsNull(): %v\n", obj.Name.IsNull())
	val, err = obj.Name.Get()
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Printf("obj.Name.Get(): %#v <nil>\n", val)
	fmt.Printf("obj.Name.GetOrEmpty(): %#v\n", obj.Name.GetOrEmpty())
	fmt.Printf("obj.Name.MustGet(): %#v\n", obj.Name.MustGet())
	fmt.Println("---")

}
Output:
Unspecified:
obj.Name.IsSpecified(): false
obj.Name.IsNull(): false
---
Null:
obj.Name.IsSpecified(): true
obj.Name.IsNull(): true
---
Zero value:
obj.Name.IsSpecified(): true
obj.Name.IsNull(): false
obj.Name.Get(): "" <nil>
obj.Name.GetOrEmpty(): ""
obj.Name.MustGet(): ""
---
Value:
obj.Name.IsSpecified(): true
obj.Name.IsNull(): false
obj.Name.Get(): "foo" <nil>
obj.Name.GetOrEmpty(): "foo"
obj.Name.MustGet(): "foo"
---

func NewNullNullable ¶

func NewNullNullable[T any]() Nullable[T]

NewNullNullable is a convenience helper to allow constructing a `Nullable` with an explicit `null`, for instance to construct a field inside a struct, without introducing an intermediate variable

Example ¶
package main

import (
	"fmt"

	"github.com/oapi-codegen/nullable"
)

func main() {
	p := struct {
		N nullable.Nullable[int]
	}{}

	p.N = nullable.NewNullNullable[int]()

	fmt.Printf("Specified: %v\n", p.N.IsSpecified())
	fmt.Printf("Null: %v\n", p.N.IsNull())
}
Output:
Specified: true
Null: true

func NewNullableWithValue ¶

func NewNullableWithValue[T any](t T) Nullable[T]

NewNullableWithValue is a convenience helper to allow constructing a `Nullable` with a given value, for instance to construct a field inside a struct, without introducing an intermediate variable

Example ¶
package main

import (
	"fmt"

	"github.com/oapi-codegen/nullable"
)

func main() {
	p := struct {
		N nullable.Nullable[int]
	}{}

	p.N = nullable.NewNullableWithValue(123)

	fmt.Println(p.N.Get())
}
Output:
123 <nil>

func (Nullable[T]) Get ¶

func (t Nullable[T]) Get() (T, error)

Get retrieves the underlying value, if present, and returns an error if the value was not present

func (Nullable[T]) GetOrEmpty ¶ added in v1.2.0

func (t Nullable[T]) GetOrEmpty() T

Dig retrieves the underlying value or returns empty value if not present or was `null`. Use Get to distinguish between these cases.

func (Nullable[T]) IsNull ¶

func (t Nullable[T]) IsNull() bool

IsNull indicate whether the field was sent, and had a value of `null`

func (Nullable[T]) IsSpecified ¶

func (t Nullable[T]) IsSpecified() bool

IsSpecified indicates whether the field was sent

func (Nullable[T]) MarshalJSON ¶

func (t Nullable[T]) MarshalJSON() ([]byte, error)

func (Nullable[T]) MustGet ¶ added in v1.1.0

func (t Nullable[T]) MustGet() T

func (*Nullable[T]) Set ¶

func (t *Nullable[T]) Set(value T)

Set sets the underlying value to a given value

func (*Nullable[T]) SetNull ¶

func (t *Nullable[T]) SetNull()

SetNull indicate that the field was sent, and had a value of `null`

func (*Nullable[T]) SetUnspecified ¶

func (t *Nullable[T]) SetUnspecified()

SetUnspecified indicate whether the field was sent

func (*Nullable[T]) UnmarshalJSON ¶

func (t *Nullable[T]) UnmarshalJSON(data []byte) error

Source Files ¶

View all Source files
  • nullable.go
Click to show internal directories.
Click to hide internal directories.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.