Compare commits

..

No commits in common. "34dd908590dc39810cbf3840893e5ba9df44844e" and "02d6e1f130f34fc31ba69c15365bdaec2188f353" have entirely different histories.

8 changed files with 125 additions and 351 deletions

View file

@ -1,31 +0,0 @@
# SPDX-FileCopyrightText: 2022-2023 The go-mail Authors
#
# SPDX-License-Identifier: CC0-1.0
# Dependency Review Action
#
# This Action will scan dependency manifest files that change as part of a Pull Request,
# surfacing known-vulnerable versions of the packages declared or updated in the PR.
# Once installed, if the workflow run is marked as required,
# PRs introducing known-vulnerable packages will be blocked from merging.
#
# Source repository: https://github.com/actions/dependency-review-action
name: 'Dependency Review'
on: [pull_request]
permissions:
contents: read
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit
- name: 'Checkout Repository'
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- name: 'Dependency Review'
uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4

View file

@ -1,21 +0,0 @@
# SPDX-FileCopyrightText: 2022 Winni Neessen <winni@neessen.dev>
#
# SPDX-License-Identifier: CC0-1.0
name: Govulncheck Security Scan
on: [push, pull_request]
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit
- name: Run govulncheck
uses: golang/govulncheck-action@dd0578b371c987f96d1185abb54344b44352bd58 # v1.0.3

View file

@ -1,80 +0,0 @@
# SPDX-FileCopyrightText: 2022-2023 The go-mail Authors
#
# SPDX-License-Identifier: CC0-1.0
# This workflow uses actions that are not certified by GitHub. They are provided
# by a third-party and are governed by separate terms of service, privacy
# policy, and support documentation.
name: Scorecard supply-chain security
on:
# For Branch-Protection check. Only the default branch is supported. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
branch_protection_rule:
# To guarantee Maintained check is occasionally updated. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
schedule:
- cron: '20 7 * * 2'
push:
branches: ["main"]
# Declare default permissions as read only.
permissions: read-all
jobs:
analysis:
name: Scorecard analysis
runs-on: ubuntu-latest
permissions:
# Needed to upload the results to code-scanning dashboard.
security-events: write
# Needed to publish results and get a badge (see publish_results below).
id-token: write
contents: read
actions: read
steps:
- name: Harden Runner
uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit
- name: "Checkout code"
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
with:
results_file: results.sarif
results_format: sarif
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
# - you want to enable the Branch-Protection check on a *public* repository, or
# - you are installing Scorecards on a *private* repository
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
# repo_token: ${{ secrets.SCORECARD_TOKEN }}
# Public repositories:
# - Publish results to OpenSSF REST API for easy access by consumers
# - Allows the repository to include the Scorecard badge.
# - See https://github.com/ossf/scorecard-action#publishing-results.
# For private repositories:
# - `publish_results` will always be set to `false`, regardless
# of the value entered here.
publish_results: true
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
with:
name: SARIF file
path: results.sarif
retention-days: 5
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@4dd16135b69a43b6c8efb853346f8437d92d3c93 # v3.26.6
with:
sarif_file: results.sarif

View file

@ -1,47 +0,0 @@
# SPDX-FileCopyrightText: 2024 Winni Neessen <winni@neessen.dev>
#
# SPDX-License-Identifier: CC0-1.0
name: SonarQube
permissions:
contents: read
on:
push:
branches:
- main
jobs:
build:
name: Build and analyze
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
egress-policy: audit
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
with:
go-version: '1.23'
- name: Run unit Tests
run: |
go test -v -race --coverprofile=./cov.out ./...
- uses: sonarsource/sonarqube-scan-action@master
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
- uses: sonarsource/sonarqube-quality-gate-action@master
timeout-minutes: 5
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

View file

@ -14,11 +14,10 @@ SPDX-License-Identifier: CC0-1.0
niljson provides a simple and efficient way to handle nullable JSON fields during the (un-)marshalling process. niljson provides a simple and efficient way to handle nullable JSON fields during the (un-)marshalling process.
In JSON, it's common to encounter fields that can be `null`, but handling these fields in Go can be cumbersome, In JSON, it's common to encounter fields that can be `null`, but handling these fields in Go can be cumbersome,
especially when dealing with primitive types like `int`, `float64`, and `bool`. These types can all be either `0` especially when dealing with primitive types like `int`, `float64`, `bool`. These types can all be either `0` (as value)
(as a value) or `null`. In Go you can always work with pointers, but these can lead to unhandled nil or `null`. In Go you can always work with pointers but these, of course, can lead to unhandled nil pointer dereferences.
pointer dereferences.
**niljson** addresses this challenge by offering a set of types that can seamlessly handle `null` values during **niljaon** addresses this challenge by offering a set of types that can seamlessly handle `null` values during
unmarshalling, allowing your Go applications to work with JSON data more naturally and with fewer boilerplate unmarshalling, allowing your Go applications to work with JSON data more naturally and with fewer boilerplate
checks for `nil` values. checks for `nil` values.

View file

@ -8,6 +8,42 @@ import (
"encoding/json" "encoding/json"
) )
// Variable is a generic variable type that can be null.
type Variable[T any] struct {
value T
notNil bool
}
// Value returns the value of the Variable
func (v *Variable[T]) Value() T {
return v.value
}
// NotNil returns true when a Variable is not nil
func (v *Variable[T]) NotNil() bool {
return v.notNil
}
// IsNil returns true when a Variable is nil
func (v *Variable[T]) IsNil() bool {
return !v.notNil
}
// Reset resets the value to the Variable to a zero value and sets it to be nil
func (v *Variable[T]) Reset() {
var newVal T
v.value = newVal
v.notNil = false
}
// NewVariable returns a new Variable of generic type
func NewVariable[T any](value T) Variable[T] {
return Variable[T]{
notNil: true,
value: value,
}
}
// NilBoolean is an boolean type that can be nil // NilBoolean is an boolean type that can be nil
type NilBoolean = Variable[bool] type NilBoolean = Variable[bool]
@ -44,46 +80,14 @@ type NilFloat64 = Variable[float64]
// NilString is a string type that can be nil // NilString is a string type that can be nil
type NilString = Variable[string] type NilString = Variable[string]
// Variable is a generic variable type that can be null. // UnmarshalJSON satisfies the json.Unmarshaler interface for generic Variable types
type Variable[T any] struct { func (v *Variable[T]) UnmarshalJSON(data []byte) error {
value T if string(data) != "null" {
notNil bool v.value = *new(T)
present bool v.notNil = true
} return json.Unmarshal(data, &v.value)
// NewVariable returns a new Variable of generic type
func NewVariable[T any](value T) Variable[T] {
return Variable[T]{
notNil: true,
value: value,
} }
} return nil
// IsNil returns true when a Variable is nil
func (v *Variable[T]) IsNil() bool {
return !v.notNil
}
// NotNil returns true when a Variable is not nil
func (v *Variable[T]) NotNil() bool {
return v.notNil
}
// Omitted returns true if a value was omitted in the JSON
func (v *Variable[T]) Omitted() bool {
return !v.present
}
// Reset resets the value to the Variable to a zero value and sets it to be nil
func (v *Variable[T]) Reset() {
var newVal T
v.value = newVal
v.notNil = false
}
// Value returns the value of the Variable
func (v *Variable[T]) Value() T {
return v.value
} }
// MarshalJSON satisfies the json.Marshaler interface for generic Variable types // MarshalJSON satisfies the json.Marshaler interface for generic Variable types
@ -93,14 +97,3 @@ func (v *Variable[T]) MarshalJSON() ([]byte, error) {
} }
return json.Marshal(v.value) return json.Marshal(v.value)
} }
// UnmarshalJSON satisfies the json.Unmarshaler interface for generic Variable types
func (v *Variable[T]) UnmarshalJSON(data []byte) error {
v.present = true
if string(data) != "null" {
v.value = *new(T)
v.notNil = true
return json.Unmarshal(data, &v.value)
}
return nil
}

View file

@ -12,17 +12,6 @@ import (
"testing" "testing"
) )
// List of common errors
const (
ErrUnmarshalFailed = "failed to unmarshal json with nil types: %s"
ErrMarshalFailed = "failed to marshal json with nil types: %s"
ErrExpectedJSONString = "expected json to be %q, got %q"
ErrExpectedJSONInt = "expected json to be %d, got %d"
ErrExpectedValue = "expected value, but got nil"
ErrExpectedNil = "expected nil, but got value"
ErrExpectedNilReset = "expected value to be nil after reset"
)
var jsonBytes = []byte( var jsonBytes = []byte(
`{ `{
"bool": true, "bool": true,
@ -48,14 +37,14 @@ func TestVariable_UnmarshalJSON_Boolean(t *testing.T) {
var jt JSONType var jt JSONType
if err := json.Unmarshal(jsonBytes, &jt); err != nil { if err := json.Unmarshal(jsonBytes, &jt); err != nil {
t.Errorf(ErrUnmarshalFailed, err) t.Errorf("failed to unmarshal json with nil types: %s", err)
} }
if jt.Value.IsNil() { if jt.Value.IsNil() {
t.Error(ErrExpectedValue) t.Errorf("expected value, but got nil")
} }
if jt.NilValue.NotNil() { if jt.NilValue.NotNil() {
t.Error(ErrExpectedNil) t.Errorf("expected nil, but got value")
} }
if !jt.Value.Value() { if !jt.Value.Value() {
t.Errorf("expected value to be true, got %t", jt.Value.Value()) t.Errorf("expected value to be true, got %t", jt.Value.Value())
@ -63,7 +52,7 @@ func TestVariable_UnmarshalJSON_Boolean(t *testing.T) {
jt.Value.Reset() jt.Value.Reset()
if jt.Value.NotNil() { if jt.Value.NotNil() {
t.Error(ErrExpectedNilReset) t.Errorf("expected value to be nil after reset")
} }
} }
@ -79,10 +68,10 @@ func TestVariable_MarshalJSON_Boolean(t *testing.T) {
} }
data, err := json.Marshal(&jt) data, err := json.Marshal(&jt)
if err != nil { if err != nil {
t.Errorf(ErrMarshalFailed, err) t.Errorf("failed to marshal json with nil types: %s", err)
} }
if !bytes.Equal(data, []byte(expected)) { if !bytes.Equal(data, []byte(expected)) {
t.Errorf(ErrExpectedJSONString, expected, string(data)) t.Errorf("expected json to be %q, got %q", expected, string(data))
} }
} }
@ -94,14 +83,14 @@ func TestVariable_UnmarshalJSON_ByteSlice(t *testing.T) {
var jt JSONType var jt JSONType
if err := json.Unmarshal(jsonBytes, &jt); err != nil { if err := json.Unmarshal(jsonBytes, &jt); err != nil {
t.Errorf(ErrUnmarshalFailed, err) t.Errorf("failed to unmarshal json with nil types: %s", err)
} }
if jt.Value.IsNil() { if jt.Value.IsNil() {
t.Error(ErrExpectedValue) t.Errorf("expected value, but got nil")
} }
if jt.NilValue.NotNil() { if jt.NilValue.NotNil() {
t.Error(ErrExpectedNil) t.Errorf("expected nil, but got value")
} }
if !bytes.Equal(jt.Value.Value(), []byte("bytes")) { if !bytes.Equal(jt.Value.Value(), []byte("bytes")) {
t.Errorf("expected value to be %q, got %q", "bytes", jt.Value.Value()) t.Errorf("expected value to be %q, got %q", "bytes", jt.Value.Value())
@ -109,7 +98,7 @@ func TestVariable_UnmarshalJSON_ByteSlice(t *testing.T) {
jt.Value.Reset() jt.Value.Reset()
if jt.Value.NotNil() { if jt.Value.NotNil() {
t.Error(ErrExpectedNilReset) t.Errorf("expected value to be nil after reset")
} }
} }
@ -125,10 +114,10 @@ func TestVariable_MarshalJSON_ByteSlice(t *testing.T) {
} }
data, err := json.Marshal(&jt) data, err := json.Marshal(&jt)
if err != nil { if err != nil {
t.Errorf(ErrMarshalFailed, err) t.Errorf("failed to marshal json with nil types: %s", err)
} }
if !bytes.Equal(data, []byte(expected)) { if !bytes.Equal(data, []byte(expected)) {
t.Errorf(ErrExpectedJSONString, expected, string(data)) t.Errorf("expected json to be %q, got %q", expected, string(data))
} }
} }
@ -141,14 +130,14 @@ func TestVariable_UnmarshalJSON_Float32(t *testing.T) {
var jt JSONType var jt JSONType
if err := json.Unmarshal(jsonBytes, &jt); err != nil { if err := json.Unmarshal(jsonBytes, &jt); err != nil {
t.Errorf(ErrUnmarshalFailed, err) t.Errorf("failed to unmarshal json with nil types: %s", err)
} }
if jt.Value.IsNil() { if jt.Value.IsNil() {
t.Error(ErrExpectedValue) t.Errorf("expected value, but got nil")
} }
if jt.NilValue.NotNil() { if jt.NilValue.NotNil() {
t.Error(ErrExpectedNil) t.Errorf("expected nil, but got value")
} }
if jt.Value.Value() != expected { if jt.Value.Value() != expected {
t.Errorf("expected value to be %f, got %f", expected, jt.Value.Value()) t.Errorf("expected value to be %f, got %f", expected, jt.Value.Value())
@ -156,7 +145,7 @@ func TestVariable_UnmarshalJSON_Float32(t *testing.T) {
jt.Value.Reset() jt.Value.Reset()
if jt.Value.NotNil() { if jt.Value.NotNil() {
t.Error(ErrExpectedNilReset) t.Errorf("expected value to be nil after reset")
} }
} }
@ -172,10 +161,10 @@ func TestVariable_MarshalJSON_Float32(t *testing.T) {
} }
data, err := json.Marshal(&jt) data, err := json.Marshal(&jt)
if err != nil { if err != nil {
t.Errorf(ErrMarshalFailed, err) t.Errorf("failed to marshal json with nil types: %s", err)
} }
if !bytes.Equal(data, []byte(expected)) { if !bytes.Equal(data, []byte(expected)) {
t.Errorf(ErrExpectedJSONString, expected, string(data)) t.Errorf("expected json to be %q, got %q", expected, string(data))
} }
} }
@ -188,14 +177,14 @@ func TestVariable_UnmarshalJSON_Float64(t *testing.T) {
var jt JSONType var jt JSONType
if err := json.Unmarshal(jsonBytes, &jt); err != nil { if err := json.Unmarshal(jsonBytes, &jt); err != nil {
t.Errorf(ErrUnmarshalFailed, err) t.Errorf("failed to unmarshal json with nil types: %s", err)
} }
if jt.Value.IsNil() { if jt.Value.IsNil() {
t.Error(ErrExpectedValue) t.Errorf("expected value, but got nil")
} }
if jt.NilValue.NotNil() { if jt.NilValue.NotNil() {
t.Error(ErrExpectedNil) t.Errorf("expected nil, but got value")
} }
if jt.Value.Value() != expected { if jt.Value.Value() != expected {
t.Errorf("expected value to be %f, got %f", expected, jt.Value.Value()) t.Errorf("expected value to be %f, got %f", expected, jt.Value.Value())
@ -203,7 +192,7 @@ func TestVariable_UnmarshalJSON_Float64(t *testing.T) {
jt.Value.Reset() jt.Value.Reset()
if jt.Value.NotNil() { if jt.Value.NotNil() {
t.Error(ErrExpectedNilReset) t.Errorf("expected value to be nil after reset")
} }
} }
@ -219,10 +208,10 @@ func TestVariable_MarshalJSON_Float64(t *testing.T) {
} }
data, err := json.Marshal(&jt) data, err := json.Marshal(&jt)
if err != nil { if err != nil {
t.Errorf(ErrMarshalFailed, err) t.Errorf("failed to marshal json with nil types: %s", err)
} }
if !bytes.Equal(data, []byte(expected)) { if !bytes.Equal(data, []byte(expected)) {
t.Errorf(ErrExpectedJSONString, expected, string(data)) t.Errorf("expected json to be %q, got %q", expected, string(data))
} }
} }
@ -235,22 +224,22 @@ func TestVariable_UnmarshalJSON_Int(t *testing.T) {
var jt JSONType var jt JSONType
if err := json.Unmarshal(jsonBytes, &jt); err != nil { if err := json.Unmarshal(jsonBytes, &jt); err != nil {
t.Errorf(ErrUnmarshalFailed, err) t.Errorf("failed to unmarshal json with nil types: %s", err)
} }
if jt.Value.IsNil() { if jt.Value.IsNil() {
t.Error(ErrExpectedValue) t.Errorf("expected value, but got nil")
} }
if jt.NilValue.NotNil() { if jt.NilValue.NotNil() {
t.Error(ErrExpectedNil) t.Errorf("expected nil, but got value")
} }
if jt.Value.Value() != expected { if jt.Value.Value() != expected {
t.Errorf(ErrExpectedJSONInt, expected, jt.Value.Value()) t.Errorf("expected value to be %d, got %d", expected, jt.Value.Value())
} }
jt.Value.Reset() jt.Value.Reset()
if jt.Value.NotNil() { if jt.Value.NotNil() {
t.Error(ErrExpectedNilReset) t.Errorf("expected value to be nil after reset")
} }
} }
@ -266,10 +255,10 @@ func TestVariable_MarshalJSON_Int(t *testing.T) {
} }
data, err := json.Marshal(&jt) data, err := json.Marshal(&jt)
if err != nil { if err != nil {
t.Errorf(ErrMarshalFailed, err) t.Errorf("failed to marshal json with nil types: %s", err)
} }
if !bytes.Equal(data, []byte(expected)) { if !bytes.Equal(data, []byte(expected)) {
t.Errorf(ErrExpectedJSONString, expected, string(data)) t.Errorf("expected json to be %q, got %q", expected, string(data))
} }
} }
@ -282,22 +271,22 @@ func TestVariable_UnmarshalJSON_Int64(t *testing.T) {
var jt JSONType var jt JSONType
if err := json.Unmarshal(jsonBytes, &jt); err != nil { if err := json.Unmarshal(jsonBytes, &jt); err != nil {
t.Errorf(ErrUnmarshalFailed, err) t.Errorf("failed to unmarshal json with nil types: %s", err)
} }
if jt.Value.IsNil() { if jt.Value.IsNil() {
t.Error(ErrExpectedValue) t.Errorf("expected value, but got nil")
} }
if jt.NilValue.NotNil() { if jt.NilValue.NotNil() {
t.Error(ErrExpectedNil) t.Errorf("expected nil, but got value")
} }
if jt.Value.Value() != expected { if jt.Value.Value() != expected {
t.Errorf(ErrExpectedJSONInt, expected, jt.Value.Value()) t.Errorf("expected value to be %d, got %d", expected, jt.Value.Value())
} }
jt.Value.Reset() jt.Value.Reset()
if jt.Value.NotNil() { if jt.Value.NotNil() {
t.Error(ErrExpectedNilReset) t.Errorf("expected value to be nil after reset")
} }
} }
@ -313,10 +302,10 @@ func TestVariable_MarshalJSON_Int64(t *testing.T) {
} }
data, err := json.Marshal(&jt) data, err := json.Marshal(&jt)
if err != nil { if err != nil {
t.Errorf(ErrMarshalFailed, err) t.Errorf("failed to marshal json with nil types: %s", err)
} }
if !bytes.Equal(data, []byte(expected)) { if !bytes.Equal(data, []byte(expected)) {
t.Errorf(ErrExpectedJSONString, expected, string(data)) t.Errorf("expected json to be %q, got %q", expected, string(data))
} }
} }
@ -329,14 +318,14 @@ func TestVariable_UnmarshalJSON_String(t *testing.T) {
var jt JSONType var jt JSONType
if err := json.Unmarshal(jsonBytes, &jt); err != nil { if err := json.Unmarshal(jsonBytes, &jt); err != nil {
t.Errorf(ErrUnmarshalFailed, err) t.Errorf("failed to unmarshal json with nil types: %s", err)
} }
if jt.Value.IsNil() { if jt.Value.IsNil() {
t.Error(ErrExpectedValue) t.Errorf("expected value, but got nil")
} }
if jt.NilValue.NotNil() { if jt.NilValue.NotNil() {
t.Error(ErrExpectedNil) t.Errorf("expected nil, but got value")
} }
if jt.Value.Value() != expected { if jt.Value.Value() != expected {
t.Errorf("expected value to be %s, got %s", expected, jt.Value.Value()) t.Errorf("expected value to be %s, got %s", expected, jt.Value.Value())
@ -344,7 +333,7 @@ func TestVariable_UnmarshalJSON_String(t *testing.T) {
jt.Value.Reset() jt.Value.Reset()
if jt.Value.NotNil() { if jt.Value.NotNil() {
t.Error(ErrExpectedNilReset) t.Errorf("expected value to be nil after reset")
} }
} }
@ -360,10 +349,10 @@ func TestVariable_MarshalJSON_String(t *testing.T) {
} }
data, err := json.Marshal(&jt) data, err := json.Marshal(&jt)
if err != nil { if err != nil {
t.Errorf(ErrMarshalFailed, err) t.Errorf("failed to marshal json with nil types: %s", err)
} }
if !bytes.Equal(data, []byte(expected)) { if !bytes.Equal(data, []byte(expected)) {
t.Errorf(ErrExpectedJSONString, expected, string(data)) t.Errorf("expected json to be %q, got %q", expected, string(data))
} }
} }
@ -376,22 +365,22 @@ func TestVariable_UnmarshalJSON_UInt(t *testing.T) {
var jt JSONType var jt JSONType
if err := json.Unmarshal(jsonBytes, &jt); err != nil { if err := json.Unmarshal(jsonBytes, &jt); err != nil {
t.Errorf(ErrUnmarshalFailed, err) t.Errorf("failed to unmarshal json with nil types: %s", err)
} }
if jt.Value.IsNil() { if jt.Value.IsNil() {
t.Error(ErrExpectedValue) t.Errorf("expected value, but got nil")
} }
if jt.NilValue.NotNil() { if jt.NilValue.NotNil() {
t.Error(ErrExpectedNil) t.Errorf("expected nil, but got value")
} }
if jt.Value.Value() != expected { if jt.Value.Value() != expected {
t.Errorf(ErrExpectedJSONInt, expected, jt.Value.Value()) t.Errorf("expected value to be %d, got %d", expected, jt.Value.Value())
} }
jt.Value.Reset() jt.Value.Reset()
if jt.Value.NotNil() { if jt.Value.NotNil() {
t.Error(ErrExpectedNilReset) t.Errorf("expected value to be nil after reset")
} }
} }
@ -407,10 +396,10 @@ func TestVariable_MarshalJSON_UInt(t *testing.T) {
} }
data, err := json.Marshal(&jt) data, err := json.Marshal(&jt)
if err != nil { if err != nil {
t.Errorf(ErrMarshalFailed, err) t.Errorf("failed to marshal json with nil types: %s", err)
} }
if !bytes.Equal(data, []byte(expected)) { if !bytes.Equal(data, []byte(expected)) {
t.Errorf(ErrExpectedJSONString, expected, string(data)) t.Errorf("expected json to be %q, got %q", expected, string(data))
} }
} }
@ -423,22 +412,22 @@ func TestVariable_UnmarshalJSON_UInt8(t *testing.T) {
var jt JSONType var jt JSONType
if err := json.Unmarshal(jsonBytes, &jt); err != nil { if err := json.Unmarshal(jsonBytes, &jt); err != nil {
t.Errorf(ErrUnmarshalFailed, err) t.Errorf("failed to unmarshal json with nil types: %s", err)
} }
if jt.Value.IsNil() { if jt.Value.IsNil() {
t.Error(ErrExpectedValue) t.Errorf("expected value, but got nil")
} }
if jt.NilValue.NotNil() { if jt.NilValue.NotNil() {
t.Error(ErrExpectedNil) t.Errorf("expected nil, but got value")
} }
if jt.Value.Value() != expected { if jt.Value.Value() != expected {
t.Errorf(ErrExpectedJSONInt, expected, jt.Value.Value()) t.Errorf("expected value to be %d, got %d", expected, jt.Value.Value())
} }
jt.Value.Reset() jt.Value.Reset()
if jt.Value.NotNil() { if jt.Value.NotNil() {
t.Error(ErrExpectedNilReset) t.Errorf("expected value to be nil after reset")
} }
} }
@ -454,10 +443,10 @@ func TestVariable_MarshalJSON_UInt8(t *testing.T) {
} }
data, err := json.Marshal(&jt) data, err := json.Marshal(&jt)
if err != nil { if err != nil {
t.Errorf(ErrMarshalFailed, err) t.Errorf("failed to marshal json with nil types: %s", err)
} }
if !bytes.Equal(data, []byte(expected)) { if !bytes.Equal(data, []byte(expected)) {
t.Errorf(ErrExpectedJSONString, expected, string(data)) t.Errorf("expected json to be %q, got %q", expected, string(data))
} }
} }
@ -470,22 +459,22 @@ func TestVariable_UnmarshalJSON_UInt16(t *testing.T) {
var jt JSONType var jt JSONType
if err := json.Unmarshal(jsonBytes, &jt); err != nil { if err := json.Unmarshal(jsonBytes, &jt); err != nil {
t.Errorf(ErrUnmarshalFailed, err) t.Errorf("failed to unmarshal json with nil types: %s", err)
} }
if jt.Value.IsNil() { if jt.Value.IsNil() {
t.Error(ErrExpectedValue) t.Errorf("expected value, but got nil")
} }
if jt.NilValue.NotNil() { if jt.NilValue.NotNil() {
t.Error(ErrExpectedNil) t.Errorf("expected nil, but got value")
} }
if jt.Value.Value() != expected { if jt.Value.Value() != expected {
t.Errorf(ErrExpectedJSONInt, expected, jt.Value.Value()) t.Errorf("expected value to be %d, got %d", expected, jt.Value.Value())
} }
jt.Value.Reset() jt.Value.Reset()
if jt.Value.NotNil() { if jt.Value.NotNil() {
t.Error(ErrExpectedNilReset) t.Errorf("expected value to be nil after reset")
} }
} }
@ -501,10 +490,10 @@ func TestVariable_MarshalJSON_UInt16(t *testing.T) {
} }
data, err := json.Marshal(&jt) data, err := json.Marshal(&jt)
if err != nil { if err != nil {
t.Errorf(ErrMarshalFailed, err) t.Errorf("failed to marshal json with nil types: %s", err)
} }
if !bytes.Equal(data, []byte(expected)) { if !bytes.Equal(data, []byte(expected)) {
t.Errorf(ErrExpectedJSONString, expected, string(data)) t.Errorf("expected json to be %q, got %q", expected, string(data))
} }
} }
@ -517,22 +506,22 @@ func TestVariable_UnmarshalJSON_UInt32(t *testing.T) {
var jt JSONType var jt JSONType
if err := json.Unmarshal(jsonBytes, &jt); err != nil { if err := json.Unmarshal(jsonBytes, &jt); err != nil {
t.Errorf(ErrUnmarshalFailed, err) t.Errorf("failed to unmarshal json with nil types: %s", err)
} }
if jt.Value.IsNil() { if jt.Value.IsNil() {
t.Error(ErrExpectedValue) t.Errorf("expected value, but got nil")
} }
if jt.NilValue.NotNil() { if jt.NilValue.NotNil() {
t.Error(ErrExpectedNil) t.Errorf("expected nil, but got value")
} }
if jt.Value.Value() != expected { if jt.Value.Value() != expected {
t.Errorf(ErrExpectedJSONInt, expected, jt.Value.Value()) t.Errorf("expected value to be %d, got %d", expected, jt.Value.Value())
} }
jt.Value.Reset() jt.Value.Reset()
if jt.Value.NotNil() { if jt.Value.NotNil() {
t.Error(ErrExpectedNilReset) t.Errorf("expected value to be nil after reset")
} }
} }
@ -548,10 +537,10 @@ func TestVariable_MarshalJSON_UInt32(t *testing.T) {
} }
data, err := json.Marshal(&jt) data, err := json.Marshal(&jt)
if err != nil { if err != nil {
t.Errorf(ErrMarshalFailed, err) t.Errorf("failed to marshal json with nil types: %s", err)
} }
if !bytes.Equal(data, []byte(expected)) { if !bytes.Equal(data, []byte(expected)) {
t.Errorf(ErrExpectedJSONString, expected, string(data)) t.Errorf("expected json to be %q, got %q", expected, string(data))
} }
} }
@ -564,22 +553,22 @@ func TestVariable_UnmarshalJSON_UInt64(t *testing.T) {
var jt JSONType var jt JSONType
if err := json.Unmarshal(jsonBytes, &jt); err != nil { if err := json.Unmarshal(jsonBytes, &jt); err != nil {
t.Errorf(ErrUnmarshalFailed, err) t.Errorf("failed to unmarshal json with nil types: %s", err)
} }
if jt.Value.IsNil() { if jt.Value.IsNil() {
t.Error(ErrExpectedValue) t.Errorf("expected value, but got nil")
} }
if jt.NilValue.NotNil() { if jt.NilValue.NotNil() {
t.Error(ErrExpectedNil) t.Errorf("expected nil, but got value")
} }
if jt.Value.Value() != expected { if jt.Value.Value() != expected {
t.Errorf(ErrExpectedJSONInt, expected, jt.Value.Value()) t.Errorf("expected value to be %d, got %d", expected, jt.Value.Value())
} }
jt.Value.Reset() jt.Value.Reset()
if jt.Value.NotNil() { if jt.Value.NotNil() {
t.Error(ErrExpectedNilReset) t.Errorf("expected value to be nil after reset")
} }
} }
@ -595,32 +584,10 @@ func TestVariable_MarshalJSON_UInt64(t *testing.T) {
} }
data, err := json.Marshal(&jt) data, err := json.Marshal(&jt)
if err != nil { if err != nil {
t.Errorf(ErrMarshalFailed, err) t.Errorf("failed to marshal json with nil types: %s", err)
} }
if !bytes.Equal(data, []byte(expected)) { if !bytes.Equal(data, []byte(expected)) {
t.Errorf(ErrExpectedJSONString, expected, string(data)) t.Errorf("expected json to be %q, got %q", expected, string(data))
}
}
func TestVariable_Omitted(t *testing.T) {
type JSONType struct {
NilValue NilBoolean `json:"nilvalue"`
Omitted NilBoolean `json:"omitted,omitempty"`
}
var jt JSONType
if err := json.Unmarshal(jsonBytes, &jt); err != nil {
t.Errorf(ErrUnmarshalFailed, err)
}
if jt.NilValue.NotNil() {
t.Error(ErrExpectedNil)
}
if jt.NilValue.Omitted() {
t.Error("expected nil value to be not omitted")
}
if !jt.Omitted.Omitted() {
t.Error("expected omitted value to be omitted")
} }
} }

View file

@ -1,6 +0,0 @@
# SPDX-FileCopyrightText: 2024 Winni Neessen <wn@neessen.dev>
#
# SPDX-License-Identifier: CC0-1.0
sonar.projectKey=niljson
sonar.go.coverage.reportPaths=cov.out