object

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jan 29, 2026 License: MIT Imports: 5 Imported by: 2

README

Object

Package object implements a JSON object with ordered properties.

Standard Go maps (map[string]any) do not guarantee key order. This package provides object.Map[V], which implements json.Marshaler and json.Unmarshaler to preserve the order of JSON object properties during serialization and deserialization.

Features

  • Ordered JSON: Preserves the order of keys as they appear in the JSON input.
  • Generics: Strongly typed values using Go generics (Map[V]).
  • Iterators: Supports Go 1.23+ iterators (iter.Seq2) for easy ranging over properties.
  • Standard Compatibility: Works seamlessly with encoding/json.

Usage

Simple Example
package main

import (
	"encoding/json"
	"fmt"

	"gitlab.com/so_literate/object"
)

func main() {
	// JSON data with specific order
	input := `{"name": "Alice", "role": "Admin", "active": true}`

	// Unmarshal into object.Map[any] to preserve order
	var data object.Map[any]
	err := json.Unmarshal([]byte(input), &data)
	if err != nil {
		panic(err)
	}

	// Iterate over properties in order
	for key, value := range data.Iter() {
		fmt.Printf("%s: %v\n", key, value)
	}

	// Marshal back to JSON, order is preserved
	out, err := json.Marshal(data)
	if err != nil {
		panic(err)
	}

	fmt.Println(string(out))
}

Documentation

Overview

Package object implements a JSON object with ordered properties.

Example
package main

import (
	"encoding/json"
	"fmt"

	"gitlab.com/so_literate/object"
)

func main() {
	type objectValue struct {
		Text  string `json:"text"`
		Slice []int  `json:"slice"`
	}

	type jsonStruct struct {
		RootText string                  `json:"root_text"`
		Object   object.Map[objectValue] `json:"object"`
	}

	data := `{"root_text":"root text","object":{"key1":{"text":"fk1","slice":[1]},"key_two":{"text":"fk2","slice":[2]}}}`
	value := jsonStruct{}

	err := json.Unmarshal([]byte(data), &value)
	if err != nil {
		fmt.Println("json.Unmarshal:", err)
		return
	}

	fmt.Println("Unmarshal:")
	fmt.Println(value.RootText)
	for _, prop := range value.Object.Properties {
		fmt.Println(prop.Key, prop.Value.Text, prop.Value.Slice)
	}

	fmt.Println("\nMarshal:")

	gotData, err := json.Marshal(value)
	if err != nil {
		fmt.Println("json.Marshal:", err)
		return
	}

	fmt.Println(string(gotData))

}
Output:


Unmarshal:
root text
key1 fk1 [1]
key_two fk2 [2]

Marshal:
{"root_text":"root text","object":{"key1":{"text":"fk1","slice":[1]},"key_two":{"text":"fk2","slice":[2]}}}

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidJSON is returned by UnmarshalJSON when the JSON input is invalid.
	ErrInvalidJSON = errors.New("invalid JSON")
	// ErrInvalidUnmarshalDestination is returned by UnmarshalJSON when the destination is invalid.
	ErrInvalidUnmarshalDestination = errors.New("invalid unmarshal destination")
)

Functions

This section is empty.

Types

type Map added in v0.1.0

type Map[V any] struct {
	Properties []Property[V]
}

Map implements MarshalJSON and UnmarshalJSON to preserve the order of JSON object properties during serialization. Standard Go maps (map[string]any) do not guarantee key order.

Example (Aliases)
package main

import (
	"encoding/json"
	"fmt"

	"gitlab.com/so_literate/object"
)

func main() {
	type obj object.Map[string]

	o := obj{
		Properties: []object.Property[string]{
			{Key: "1", Value: "1"},
		},
	}

	res, err := json.Marshal(o)
	if err != nil {
		panic(err)
	}

	// It prints Properties field when you use object.Map as an alias type.
	fmt.Println(string(res))

}
Output:


{"Properties":[{"Key":"1","Value":"1"}]}
Example (Any)
package main

import (
	"encoding/json"
	"fmt"

	"gitlab.com/so_literate/object"
)

func main() {
	// JSON data with specific order
	input := `{"name": "Alice", "role": "Admin", "active": true}`

	// Unmarshal into object.Map[any] to preserve order
	var data object.Map[any]
	err := json.Unmarshal([]byte(input), &data)
	if err != nil {
		panic(err)
	}

	// Iterate over properties in order
	for key, value := range data.Iter() {
		fmt.Printf("%s: %v\n", key, value)
	}

	// Marshal back to JSON, order is preserved
	out, err := json.Marshal(data)
	if err != nil {
		panic(err)
	}

	fmt.Println(string(out))

}
Output:


name: Alice
role: Admin
active: true
{"name":"Alice","role":"Admin","active":true}

func (*Map[V]) Add added in v0.1.1

func (m *Map[V]) Add(key string, value V)

Add appends the provided key and value to the object's properties. It does not check for duplicate keys.

func (Map[V]) Get added in v0.1.0

func (m Map[V]) Get(key string) (v V, ok bool)

Get returns the value associated with the given key. This operation is O(N) because it performs a linear search.

func (Map[V]) Iter added in v0.1.0

func (m Map[V]) Iter() iter.Seq2[string, V]

Iter returns an iterator over the object's properties. It yields each key-value pair in order.

Example
package main

import (
	"fmt"

	"gitlab.com/so_literate/object"
)

func main() {
	type objectValue struct {
		Text  string `json:"text"`
		Slice []int  `json:"slice"`
	}

	obj := object.Map[*objectValue]{
		Properties: []object.Property[*objectValue]{
			{
				Key: "key1",
				Value: &objectValue{
					Text:  "text1",
					Slice: []int{1, 11},
				},
			},
			{
				Key: "key2",
				Value: &objectValue{
					Text:  "text2",
					Slice: []int{2, 22},
				},
			},
		},
	}

	for key, value := range obj.Iter() {
		fmt.Printf("Key: %s, Value: %s, %v\n", key, value.Text, value.Slice)
	}

}
Output:

Key: key1, Value: text1, [1 11]
Key: key2, Value: text2, [2 22]

func (Map[V]) MarshalJSON added in v0.1.0

func (m Map[V]) MarshalJSON() ([]byte, error)

MarshalJSON implements the json.Marshaler interface. It encodes properties as a JSON object, e.g., {"name":"John"}.

func (*Map[V]) Put added in v0.1.1

func (m *Map[V]) Put(key string, value V)

Put sets the value for the specified key. If the key already exists, its value is updated. Otherwise, the key-value pair is appended. This operation performs a linear search (O(N)).

func (*Map[V]) UnmarshalJSON added in v0.1.0

func (m *Map[V]) UnmarshalJSON(data []byte) error

UnmarshalJSON implements the json.Unmarshaler interface. It decodes the JSON object's keys and values, preserving their order.

type Property added in v0.1.0

type Property[V any] struct {
	Key   string
	Value V
}

Property represents a key-value pair in a JSON object. Keys must be strings, and values must be valid JSON data types: string, number, object, array, boolean, or null.

Jump to

Keyboard shortcuts

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