jsonull

package
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 23, 2026 License: MIT Imports: 3 Imported by: 1

README

jsonull

jsonull is a Go package that provides a generic nullable type for JSON handling with three-state logic. It allows you to distinguish between:

  • A field not present in JSON
  • A field explicitly set to null
  • A field with an actual value

This is particularly useful for PATCH endpoints and partial updates where you need to differentiate between "don't update this field" and "set this field to null".

Features

  • Three-state logic: Not present, null, or valid value
  • Generic implementation: Works with any type using Go generics
  • Type-safe: Compile-time type checking
  • JSON compatible: Implements json.Marshaler and json.Unmarshaler
  • Comprehensive API: Helper methods for common operations
  • Well-tested: 96.9% test coverage
  • Zero dependencies: Only uses Go standard library

Installation

go get github.com/atfromhome/goreus/pkg/jsonull

Quick Start

package main

import (
    "encoding/json"
    "fmt"
    "github.com/atfromhome/goreus/pkg/jsonull"
)

type User struct {
    Name  string               `json:"name"`
    Email jsonull.JsonNull[string] `json:"email,omitempty"`
    Age   jsonull.JsonNull[int]    `json:"age,omitempty"`
}

func main() {
    // Example 1: Field with value
    json1 := `{"name":"John","email":"john@example.com","age":30}`
    var user1 User
    json.Unmarshal([]byte(json1), &user1)
    
    fmt.Println(user1.Email.IsSet())    // true
    fmt.Println(user1.Email.Value)      // "john@example.com"
    
    // Example 2: Field explicitly null
    json2 := `{"name":"Jane","email":null,"age":25}`
    var user2 User
    json.Unmarshal([]byte(json2), &user2)
    
    fmt.Println(user2.Email.IsNull())   // true
    fmt.Println(user2.Email.Present)    // true
    fmt.Println(user2.Email.Valid)      // false
    
    // Example 3: Field not present
    json3 := `{"name":"Bob"}`
    var user3 User
    json.Unmarshal([]byte(json3), &user3)
    
    fmt.Println(user3.Email.Present)    // false
    fmt.Println(user3.Email.IsSet())    // false
    fmt.Println(user3.Email.IsNull())   // false
}

Use Cases

PATCH Endpoints

Perfect for HTTP PATCH operations where you need to distinguish between:

// PATCH /api/users/123
type UpdateUserRequest struct {
    Name  jsonull.JsonNull[string] `json:"name,omitempty"`
    Email jsonull.JsonNull[string] `json:"email,omitempty"`
    Age   jsonull.JsonNull[int]    `json:"age,omitempty"`
}

func UpdateUser(w http.ResponseWriter, r *http.Request) {
    var req UpdateUserRequest
    json.NewDecoder(r.Body).Decode(&req)
    
    // Request: {"email": null}
    if req.Email.IsNull() {
        // User explicitly wants to delete their email
        deleteUserEmail(userID)
    }
    
    // Request: {"name": "New Name"}
    if req.Name.IsSet() {
        // User wants to update their name
        updateUserName(userID, req.Name.Value)
    }
    
    // Request: {}
    if !req.Age.Present {
        // Age field not sent, don't touch it
        // Do nothing with age
    }
}
Optional Fields in APIs
type Product struct {
    Name        string                  `json:"name"`
    Description jsonull.JsonNull[string]  `json:"description,omitempty"`
    Price       jsonull.JsonNull[float64] `json:"price,omitempty"`
    Stock       jsonull.JsonNull[int]     `json:"stock,omitempty"`
}

API Reference

Types
type JsonNull[T any] struct {
    Value   T     // The actual value
    Valid   bool  // True if value is valid (not null)
    Present bool  // True if field was present in JSON
}
Constructors
NewJsonNull[T](value T) JsonNull[T]

Creates a JsonNull with a valid value.

email := jsonull.NewJsonNull("user@example.com")
// email.Present = true
// email.Valid = true
// email.Value = "user@example.com"
NewJsonNullNull[T]() JsonNull[T]

Creates a JsonNull representing an explicit null value.

email := jsonull.NewJsonNullNull[string]()
// email.Present = true
// email.Valid = false
// email.IsNull() = true
JsonNullFromPtr[T](ptr *T) JsonNull[T]

Creates JsonNull from a pointer. Returns null if pointer is nil.

var ptr *string = nil
email := jsonull.JsonNullFromPtr(ptr)
// email.IsNull() = true

str := "test@example.com"
email2 := jsonull.JsonNullFromPtr(&str)
// email2.IsSet() = true
// email2.Value = "test@example.com"
Methods
IsNull() bool

Returns true if the field was explicitly set to null in JSON.

// JSON: {"email": null}
user.Email.IsNull() // true
IsSet() bool

Returns true if the field has a valid value.

// JSON: {"email": "user@example.com"}
user.Email.IsSet() // true
Ptr() *T

Returns a pointer to the value if valid, otherwise returns nil.

email := jsonull.NewJsonNull("user@example.com")
ptr := email.Ptr() // *string pointing to "user@example.com"

nullEmail := jsonull.NewJsonNullNull[string]()
ptr2 := nullEmail.Ptr() // nil
OrDefault(defaultValue T) T

Returns the value if valid, otherwise returns the provided default.

email := jsonull.NewJsonNull("user@example.com")
result := email.OrDefault("default@example.com") // "user@example.com"

nullEmail := jsonull.NewJsonNullNull[string]()
result2 := nullEmail.OrDefault("default@example.com") // "default@example.com"
MustGet() T

Returns the value or panics if not valid. Use with caution!

email := jsonull.NewJsonNull("user@example.com")
value := email.MustGet() // "user@example.com"

nullEmail := jsonull.NewJsonNullNull[string]()
value2 := nullEmail.MustGet() // panics!
String() string

Returns a string representation for debugging.

email := jsonull.NewJsonNull("user@example.com")
fmt.Println(email.String()) // "JsonNull{user@example.com}"

nullEmail := jsonull.NewJsonNullNull[string]()
fmt.Println(nullEmail.String()) // "JsonNull{null}"

var notPresent jsonull.JsonNull[string]
fmt.Println(notPresent.String()) // "JsonNull{not present}"

Zero Value Behavior

The zero value of JsonNull[T] has:

  • Present = false
  • Valid = false
  • Value = zero value of T

This represents a value that was not present in the JSON.

var email jsonull.JsonNull[string]
fmt.Println(email.Present) // false
fmt.Println(email.IsSet())  // false
fmt.Println(email.IsNull()) // false

Thread Safety

⚠️ JsonNull is not thread-safe. If you need to use it concurrently, you must provide external synchronization (e.g., using sync.RWMutex).

Comparison with Other Approaches

vs *pointer
// Using pointer
type User struct {
    Email *string `json:"email,omitempty"`
}
// ❌ Cannot distinguish between null and not present
// ❌ nil pointer means both "not sent" and "null"

// Using JsonNull
type User struct {
    Email jsonull.JsonNull[string] `json:"email,omitempty"`
}
// ✅ Clear distinction: Present=false vs IsNull()=true
vs sql.NullString
// Using sql.NullString
type User struct {
    Email sql.NullString `json:"email"`
}
// ❌ Cannot distinguish between null and not present
// ❌ Not generic (need different types for each data type)

// Using JsonNull
type User struct {
    Email jsonull.JsonNull[string] `json:"email,omitempty"`
}
// ✅ Three-state logic
// ✅ Works with any type

Performance

Benchmarks on Apple M2:

BenchmarkNewJsonNull-8       	1000000000	         0.32 ns/op	       0 B/op	       0 allocs/op
BenchmarkJsonNullFromPtr-8   	1000000000	         0.30 ns/op	       0 B/op	       0 allocs/op
BenchmarkUnmarshalJSON-8     	 1217712	       990.4 ns/op	     752 B/op	      10 allocs/op
BenchmarkMarshalJSON-8       	 2140656	       568.5 ns/op	     208 B/op	       7 allocs/op

Testing

Run tests:

go test ./pkg/jsonull/

Run tests with coverage:

go test -cover ./pkg/jsonull/

Run benchmarks:

go test -bench=. -benchmem ./pkg/jsonull/

Examples

Complete CRUD Example
type Article struct {
    ID      int                       `json:"id"`
    Title   string                    `json:"title"`
    Content jsonull.JsonNull[string]  `json:"content,omitempty"`
    Tags    jsonull.JsonNull[[]string] `json:"tags,omitempty"`
    Views   jsonull.JsonNull[int]     `json:"views,omitempty"`
}

// CREATE - all fields have values
func CreateArticle() {
    article := Article{
        ID:      1,
        Title:   "Hello World",
        Content: jsonull.NewJsonNull("Article content here"),
        Tags:    jsonull.NewJsonNull([]string{"go", "programming"}),
        Views:   jsonull.NewJsonNull(100),
    }
    
    data, _ := json.Marshal(article)
    fmt.Println(string(data))
    // {"id":1,"title":"Hello World","content":"Article content here","tags":["go","programming"],"views":100}
}

// UPDATE - partial update with PATCH
func UpdateArticle(data []byte) {
    var article Article
    json.Unmarshal(data, &article)
    
    // Patch: {"content": null}
    if article.Content.IsNull() {
        fmt.Println("Delete content")
    }
    
    // Patch: {"tags": ["updated", "tags"]}
    if article.Tags.IsSet() {
        fmt.Println("Update tags to:", article.Tags.Value)
    }
    
    // Patch: {}
    if !article.Views.Present {
        fmt.Println("Don't touch views")
    }
}
Working with Complex Types
type Config struct {
    Settings jsonull.JsonNull[map[string]interface{}] `json:"settings,omitempty"`
    Features jsonull.JsonNull[[]string]               `json:"features,omitempty"`
    Metadata jsonull.JsonNull[struct {
        Author  string `json:"author"`
        Version string `json:"version"`
    }] `json:"metadata,omitempty"`
}

func ProcessConfig() {
    jsonData := `{
        "settings": {"theme": "dark", "locale": "en"},
        "features": ["feature1", "feature2"],
        "metadata": null
    }`
    
    var config Config
    json.Unmarshal([]byte(jsonData), &config)
    
    if config.Settings.IsSet() {
        fmt.Println("Settings:", config.Settings.Value)
    }
    
    if config.Metadata.IsNull() {
        fmt.Println("Metadata was explicitly set to null")
    }
}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This package is part of the goreus project.

Documentation

Overview

Example

Example demonstrates basic usage of JsonNull

package main

import (
	"encoding/json"
	"fmt"

	"github.com/atfromhome/goreus/pkg/jsonull"
)

func main() {
	type User struct {
		Name  string                   `json:"name"`
		Email jsonull.JsonNull[string] `json:"email,omitempty"`
	}

	// Field with value
	json1 := `{"name":"John","email":"john@example.com"}`
	var user1 User
	json.Unmarshal([]byte(json1), &user1)
	fmt.Println("IsSet:", user1.Email.IsSet())
	fmt.Println("Value:", user1.Email.Value)

	// Field explicitly null
	json2 := `{"name":"Jane","email":null}`
	var user2 User
	json.Unmarshal([]byte(json2), &user2)
	fmt.Println("IsNull:", user2.Email.IsNull())

	// Field not present
	json3 := `{"name":"Bob"}`
	var user3 User
	json.Unmarshal([]byte(json3), &user3)
	fmt.Println("Present:", user3.Email.Present)

}
Output:
IsSet: true
Value: john@example.com
IsNull: true
Present: false
Example (ComplexTypes)

Example_complexTypes demonstrates using JsonNull with complex types

package main

import (
	"encoding/json"
	"fmt"

	"github.com/atfromhome/goreus/pkg/jsonull"
)

func main() {
	type Config struct {
		Settings jsonull.JsonNull[map[string]string] `json:"settings,omitempty"`
		Tags     jsonull.JsonNull[[]string]          `json:"tags,omitempty"`
	}

	jsonData := `{
		"settings": {"theme": "dark", "locale": "en"},
		"tags": ["go", "programming"]
	}`

	var config Config
	json.Unmarshal([]byte(jsonData), &config)

	if config.Settings.IsSet() {
		fmt.Println("Theme:", config.Settings.Value["theme"])
		fmt.Println("Locale:", config.Settings.Value["locale"])
	}

	if config.Tags.IsSet() {
		fmt.Println("Tags:", config.Tags.Value)
	}

}
Output:
Theme: dark
Locale: en
Tags: [go programming]
Example (PatchEndpoint)

Example_patchEndpoint demonstrates using JsonNull for PATCH endpoints

package main

import (
	"encoding/json"
	"fmt"

	"github.com/atfromhome/goreus/pkg/jsonull"
)

func main() {
	type UpdateUserRequest struct {
		Name  jsonull.JsonNull[string] `json:"name,omitempty"`
		Email jsonull.JsonNull[string] `json:"email,omitempty"`
		Age   jsonull.JsonNull[int]    `json:"age,omitempty"`
	}

	// Scenario 1: Delete email (set to null)
	req1 := `{"email":null}`
	var update1 UpdateUserRequest
	json.Unmarshal([]byte(req1), &update1)
	if update1.Email.IsNull() {
		fmt.Println("Scenario 1: Delete email")
	}

	// Scenario 2: Update name
	req2 := `{"name":"New Name"}`
	var update2 UpdateUserRequest
	json.Unmarshal([]byte(req2), &update2)
	if update2.Name.IsSet() {
		fmt.Println("Scenario 2: Update name to:", update2.Name.Value)
	}
	if !update2.Email.Present {
		fmt.Println("Scenario 2: Don't touch email")
	}

	// Scenario 3: Update multiple fields
	req3 := `{"name":"John","age":30}`
	var update3 UpdateUserRequest
	json.Unmarshal([]byte(req3), &update3)
	if update3.Name.IsSet() {
		fmt.Println("Scenario 3: Update name to:", update3.Name.Value)
	}
	if update3.Age.IsSet() {
		fmt.Println("Scenario 3: Update age to:", update3.Age.Value)
	}

}
Output:
Scenario 1: Delete email
Scenario 2: Update name to: New Name
Scenario 2: Don't touch email
Scenario 3: Update name to: John
Scenario 3: Update age to: 30

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type JsonNull

type JsonNull[T any] struct {
	Value   T
	Valid   bool
	Present bool
}

JsonNull represents a nullable value of type T that can distinguish between: - Not present in JSON (Present=false) - Present as null (Present=true, Valid=false) - Present with value (Present=true, Valid=true)

This is particularly useful for API endpoints that need to differentiate between: - A field not being sent in the request (no update) - A field explicitly set to null (delete/clear the value) - A field set to a specific value (update with new value)

Zero Value Behavior: The zero value of JsonNull[T] has Present=false, Valid=false, and Value=zero value of T. This represents a value that was not present in the JSON.

Thread Safety: JsonNull is not thread-safe. If used concurrently, external synchronization is required.

Example Usage:

type User struct {
    Name  string           `json:"name"`
    Email JsonNull[string] `json:"email,omitempty"`
    Age   JsonNull[int]    `json:"age,omitempty"`
}

// PATCH /users/:id
// Request: {"email": null}
// Result: user.Email.IsNull() == true (explicitly clear email)

// Request: {"name": "John"}
// Result: user.Email.Present == false (don't touch email)

// Request: {"email": "john@example.com"}
// Result: user.Email.IsSet() == true (update email)

func JsonNullFromPtr

func JsonNullFromPtr[T any](ptr *T) JsonNull[T]

JsonNullFromPtr creates JsonNull from pointer. If ptr is nil, returns a JsonNull representing null (Present=true, Valid=false). Otherwise, returns a JsonNull with the dereferenced value.

Example:

var ptr *string = nil
email := JsonNullFromPtr(ptr)
// email.IsNull() == true

str := "test@example.com"
email2 := JsonNullFromPtr(&str)
// email2.IsSet() == true
// email2.Value == "test@example.com"
Example

ExampleJsonNullFromPtr demonstrates creating JsonNull from a pointer

package main

import (
	"fmt"

	"github.com/atfromhome/goreus/pkg/jsonull"
)

func main() {
	// From nil pointer
	var ptr *string = nil
	email1 := jsonull.JsonNullFromPtr(ptr)
	fmt.Println("From nil pointer - IsNull:", email1.IsNull())

	// From valid pointer
	str := "test@example.com"
	email2 := jsonull.JsonNullFromPtr(&str)
	fmt.Println("From valid pointer - IsSet:", email2.IsSet())
	fmt.Println("From valid pointer - Value:", email2.Value)

}
Output:
From nil pointer - IsNull: true
From valid pointer - IsSet: true
From valid pointer - Value: test@example.com

func NewJsonNull

func NewJsonNull[T any](value T) JsonNull[T]

NewJsonNull creates a new JsonNull[T] with the given value. The returned JsonNull will have Present=true and Valid=true.

Example:

email := NewJsonNull("user@example.com")
// email.Value = "user@example.com"
// email.Valid = true
// email.Present = true
Example

ExampleNewJsonNull demonstrates creating a JsonNull with a value

package main

import (
	"fmt"

	"github.com/atfromhome/goreus/pkg/jsonull"
)

func main() {
	email := jsonull.NewJsonNull("user@example.com")
	fmt.Println("Present:", email.Present)
	fmt.Println("Valid:", email.Valid)
	fmt.Println("Value:", email.Value)

}
Output:
Present: true
Valid: true
Value: user@example.com

func NewJsonNullNull

func NewJsonNullNull[T any]() JsonNull[T]

NewJsonNullNull creates a new JsonNull[T] representing an explicit null value. The returned JsonNull will have Present=true and Valid=false.

Example:

email := NewJsonNullNull[string]()
// email.IsNull() == true
Example

ExampleNewJsonNullNull demonstrates creating a JsonNull representing null

package main

import (
	"fmt"

	"github.com/atfromhome/goreus/pkg/jsonull"
)

func main() {
	email := jsonull.NewJsonNullNull[string]()
	fmt.Println("Present:", email.Present)
	fmt.Println("Valid:", email.Valid)
	fmt.Println("IsNull:", email.IsNull())

}
Output:
Present: true
Valid: false
IsNull: true

func (JsonNull[T]) IsNull

func (j JsonNull[T]) IsNull() bool

IsNull returns true if the value is present but null. This means the field was explicitly set to null in the JSON.

Example

ExampleJsonNull_IsNull demonstrates the IsNull method

package main

import (
	"fmt"

	"github.com/atfromhome/goreus/pkg/jsonull"
)

func main() {
	// Explicitly null value
	nullValue := jsonull.NewJsonNullNull[string]()
	fmt.Println("Null value:", nullValue.IsNull())

	// Valid value
	validValue := jsonull.NewJsonNull("test")
	fmt.Println("Valid value:", validValue.IsNull())

	// Not present
	var notPresent jsonull.JsonNull[string]
	fmt.Println("Not present:", notPresent.IsNull())

}
Output:
Null value: true
Valid value: false
Not present: false

func (JsonNull[T]) IsSet

func (j JsonNull[T]) IsSet() bool

IsSet returns true if the value is present and valid. This means the field was set to an actual value in the JSON.

Example

ExampleJsonNull_IsSet demonstrates the IsSet method

package main

import (
	"fmt"

	"github.com/atfromhome/goreus/pkg/jsonull"
)

func main() {
	// Valid value
	validValue := jsonull.NewJsonNull("test")
	fmt.Println("Valid value:", validValue.IsSet())

	// Null value
	nullValue := jsonull.NewJsonNullNull[string]()
	fmt.Println("Null value:", nullValue.IsSet())

	// Not present
	var notPresent jsonull.JsonNull[string]
	fmt.Println("Not present:", notPresent.IsSet())

}
Output:
Valid value: true
Null value: false
Not present: false

func (JsonNull[T]) MarshalJSON

func (j JsonNull[T]) MarshalJSON() ([]byte, error)

MarshalJSON marshals the value into JSON. If Valid is false, returns the JSON null value. Otherwise, marshals the contained value.

Example

ExampleJsonNull_MarshalJSON demonstrates JSON marshaling

package main

import (
	"encoding/json"
	"fmt"

	"github.com/atfromhome/goreus/pkg/jsonull"
)

func main() {
	type Data struct {
		Value jsonull.JsonNull[string] `json:"value"`
	}

	// Valid value
	d1 := Data{Value: jsonull.NewJsonNull("test")}
	json1, _ := json.Marshal(d1)
	fmt.Println("Valid:", string(json1))

	// Null value
	d2 := Data{Value: jsonull.NewJsonNullNull[string]()}
	json2, _ := json.Marshal(d2)
	fmt.Println("Null:", string(json2))

	// Not present (zero value will marshal to null)
	d3 := Data{}
	json3, _ := json.Marshal(d3)
	fmt.Println("Not present (zero value):", string(json3))

}
Output:
Valid: {"value":"test"}
Null: {"value":null}
Not present (zero value): {"value":null}

func (JsonNull[T]) MustGet

func (j JsonNull[T]) MustGet() T

MustGet returns the value or panics if not valid. Use this only when you are certain the value is valid.

Example:

email := NewJsonNull("user@example.com")
value := email.MustGet() // "user@example.com"

nullEmail := NewJsonNullNull[string]()
value2 := nullEmail.MustGet() // panics!
Example

ExampleJsonNull_MustGet demonstrates the MustGet method

package main

import (
	"fmt"

	"github.com/atfromhome/goreus/pkg/jsonull"
)

func main() {
	// Valid value - safe to use
	validValue := jsonull.NewJsonNull("test")
	value := validValue.MustGet()
	fmt.Println("Value:", value)

}
Output:
Value: test

func (JsonNull[T]) OrDefault

func (j JsonNull[T]) OrDefault(defaultValue T) T

OrDefault returns the value if valid, otherwise returns the provided default value. This is a safe way to extract a value with a fallback.

Example:

email := NewJsonNull("user@example.com")
result := email.OrDefault("default@example.com") // "user@example.com"

nullEmail := NewJsonNullNull[string]()
result2 := nullEmail.OrDefault("default@example.com") // "default@example.com"
Example

ExampleJsonNull_OrDefault demonstrates the OrDefault method

package main

import (
	"fmt"

	"github.com/atfromhome/goreus/pkg/jsonull"
)

func main() {
	// Valid value
	validValue := jsonull.NewJsonNull("user@example.com")
	email := validValue.OrDefault("default@example.com")
	fmt.Println("Valid value:", email)

	// Null value
	nullValue := jsonull.NewJsonNullNull[string]()
	email2 := nullValue.OrDefault("default@example.com")
	fmt.Println("Null value:", email2)

	// Not present
	var notPresent jsonull.JsonNull[string]
	email3 := notPresent.OrDefault("default@example.com")
	fmt.Println("Not present:", email3)

}
Output:
Valid value: user@example.com
Null value: default@example.com
Not present: default@example.com

func (JsonNull[T]) Ptr

func (j JsonNull[T]) Ptr() *T

Ptr returns a pointer to the value if it is valid, otherwise returns nil. This is useful when you need to convert JsonNull to a standard pointer type.

Example:

email := NewJsonNull("user@example.com")
ptr := email.Ptr() // *string pointing to "user@example.com"

nullEmail := NewJsonNullNull[string]()
ptr2 := nullEmail.Ptr() // nil
Example

ExampleJsonNull_Ptr demonstrates the Ptr method

package main

import (
	"fmt"

	"github.com/atfromhome/goreus/pkg/jsonull"
)

func main() {
	// Valid value
	validValue := jsonull.NewJsonNull("test")
	ptr := validValue.Ptr()
	if ptr != nil {
		fmt.Println("Valid value pointer:", *ptr)
	}

	// Null value
	nullValue := jsonull.NewJsonNullNull[string]()
	ptr2 := nullValue.Ptr()
	fmt.Println("Null value pointer is nil:", ptr2 == nil)

}
Output:
Valid value pointer: test
Null value pointer is nil: true

func (JsonNull[T]) String

func (j JsonNull[T]) String() string

String returns a string representation of the JsonNull value. Useful for debugging and logging.

Example:

email := NewJsonNull("user@example.com")
fmt.Println(email.String()) // "JsonNull{user@example.com}"

nullEmail := NewJsonNullNull[string]()
fmt.Println(nullEmail.String()) // "JsonNull{null}"

var notPresent JsonNull[string]
fmt.Println(notPresent.String()) // "JsonNull{not present}"
Example

ExampleJsonNull_String demonstrates the String method

package main

import (
	"fmt"

	"github.com/atfromhome/goreus/pkg/jsonull"
)

func main() {
	// Valid value
	validValue := jsonull.NewJsonNull("test")
	fmt.Println(validValue.String())

	// Null value
	nullValue := jsonull.NewJsonNullNull[string]()
	fmt.Println(nullValue.String())

	// Not present
	var notPresent jsonull.JsonNull[string]
	fmt.Println(notPresent.String())

}
Output:
JsonNull{test}
JsonNull{null}
JsonNull{not present}

func (*JsonNull[T]) UnmarshalJSON

func (j *JsonNull[T]) UnmarshalJSON(data []byte) error

UnmarshalJSON unmarshals the JSON data into the value. MUST use pointer receiver to modify the struct fields.

This method sets Present=true to indicate the field was in the JSON. If the JSON value is null, Valid is set to false. If the JSON value is a valid value, Valid is set to true and Value is populated. If unmarshaling fails, an error is returned and Valid remains false.

Example

ExampleJsonNull_UnmarshalJSON demonstrates JSON unmarshaling

package main

import (
	"encoding/json"
	"fmt"

	"github.com/atfromhome/goreus/pkg/jsonull"
)

func main() {
	type Data struct {
		Value jsonull.JsonNull[int] `json:"value,omitempty"`
	}

	// Valid value
	var d1 Data
	json.Unmarshal([]byte(`{"value":42}`), &d1)
	fmt.Println("Valid - IsSet:", d1.Value.IsSet(), "Value:", d1.Value.Value)

	// Null value
	var d2 Data
	json.Unmarshal([]byte(`{"value":null}`), &d2)
	fmt.Println("Null - IsNull:", d2.Value.IsNull())

	// Not present
	var d3 Data
	json.Unmarshal([]byte(`{}`), &d3)
	fmt.Println("Not present - Present:", d3.Value.Present)

}
Output:
Valid - IsSet: true Value: 42
Null - IsNull: true
Not present - Present: false

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL