A reflection-based library for manipulating dynamic, JSON-like data structures in Go. It provides tools for traversing, modifying, validating, and converting deeply nested objects (maps, structs, slices, arrays) using JSONPath.
- Dynamic Object Manipulation: Get, Set, Delete, and Iterate over values in deeply nested structures using JSONPath.
- Schema Validation: Define schemas for your data and validate dynamic objects against them at runtime.
- Type Conversion: Convert loosely typed data (e.g.,
map[string]any) into strongly typed Go structs, maps, and slices based on schema definitions. - Deserialization: Helpers for loading JSON and YAML data directly into schema-validated structures.
- JSONPath Support: Supports dot notation, recursive descent (
..), wildcards (*), unions (['a','b']), and array slicing ([start:end:step]).
| Tool | Description | Link |
|---|---|---|
| Go | Official Website | |
| Task |
Task runner / build tool. You can use the provided shell script taskw that automatically downloads the binary and installs it in the |
Official Website |
| Docker / Podman | Optional container engine for isolated development environment. | Docker / Podman |
After building the dev container, below is a sample script that runs the container and mounts the project directory into the container:
#!/bin/bash
CONTAINER_ENGINE="podman"
CONTAINER="projects-go-json"
NETWORK="systemd-leap"
NETWORK_ALIAS="projects-go-json"
CONTAINER_UID=1000
IMAGE="localhost/projects/go-json:latest"
SSH_PORT="127.0.0.1:2200" # for local proxy vscode ssh access
PROJECT_DIRECTORY="$(pwd)"
# Check if container exists (Running or Stopped)
if $CONTAINER_ENGINE ps -a --format '{{.Names}}' | grep -q "^$CONTAINER$"; then
echo " Found existing container: $CONTAINER"
# Check if it is currently running
if $CONTAINER_ENGINE ps --format '{{.Names}}' | grep -q "^$CONTAINER$"; then
echo "✅ Container is already running."
else
echo "🔄 Container stopped. Starting it..."
$CONTAINER_ENGINE start $CONTAINER
echo "✅ Started."
fi
else
# Container doesn't exist -> Create and Run it
echo "🆕 Container not found. Creating new..."
$CONTAINER_ENGINE run -d \
# start container from scratch
# `sudo` is used because systemd-leap network was created in `sudo`
# Ensure container image exists in `sudo`
# Not needed if target network is not in `sudo`
sudo podman run -d \
--name $CONTAINER \
--network $NETWORK \
--network-alias $NETWORK_ALIAS \
--user $CONTAINER_UID:$CONTAINER_UID \
-p $SSH_PORT:22 \
-v $PROJECT_DIRECTORY:/home/dev/go-json:Z \
$IMAGE
echo "✅ Created and Started."
figo get github.com/rogonion/go-jsonThis project uses Taskfile to manage the development environment and tasks.
| Task | Description | Usage |
|---|---|---|
env:build |
Build the dev container image. Image runs an ssh server one can connect to with vscode. |
task env:build |
env:info |
Show current environment configuration. | task env:info |
deps |
Download and tidy dependencies. | task deps |
test |
Run tests. Supports optional TARGET variable. |
task testtask test TARGET=./object |
The object package is the core of the library, allowing you to manipulate data structures.
Key Capabilities:
Get: Retrieve values.Set: Update or insert values (auto-creates nested structures if schema is provided).Delete: Remove values.ForEach: Iterate over matches.AreEqual: Deep comparison.
Example:
package main
import (
"fmt"
"github.com/rogonion/go-json/object"
)
func main() {
data := map[string]any{
"users": []any{
map[string]any{"name": "Alice", "id": 1},
map[string]any{"name": "Bob", "id": 2},
},
}
obj := object.NewObject().WithSourceInterface(data)
// Get
val, _ := obj.Get("$.users[0].name")
fmt.Println(obj.GetValueFoundInterface()) // Output: Alice
// Set
obj.Set("$.users[1].active", true)
// Delete
obj.Delete("$.users[0]")
}The schema package allows you to define the expected structure of your data. This is useful for validation and conversion of dynamic data.
Example: Validation
package main
import (
"reflect"
"github.com/rogonion/go-json/schema"
)
func main() {
// Define a schema
userSchema := &schema.DynamicSchemaNode{
Kind: reflect.Struct,
Type: reflect.TypeOf(struct{ Name string; Age int }{}),
ChildNodes: schema.ChildNodes{
"Name": &schema.DynamicSchemaNode{Kind: reflect.String, Type: reflect.TypeOf("")},
"Age": &schema.DynamicSchemaNode{Kind: reflect.Int, Type: reflect.TypeOf(0)},
},
}
validator := schema.NewValidation()
data := map[string]any{"Name": "Alice", "Age": 30}
// Validate
ok, err := validator.ValidateData(data, userSchema)
}Example: Conversion
package main
import (
"reflect"
"github.com/rogonion/go-json/schema"
)
func main() {
// Define schema (same as above)
// ...
source := map[string]any{"Name": "Alice", "Age": "30"} // Age is string in source
var dest struct{ Name string; Age int }
converter := schema.NewConversion()
// Converts and coerces types (string "30" -> int 30)
err := converter.Convert(source, userSchema, &dest)
}The path package handles parsing of JSONPath strings. It is primarily used internally by the object package but can be used directly to inspect paths.
import "github.com/rogonion/go-json/path"
p := path.JSONPath("$.store.book[*].author")
segments := p.Parse()The library supports reflection-based manipulation of:
- Primitives:
int(all sizes),uint(all sizes),float32/64,bool,string. - Collections:
map,struct,slice,array. - Pointers: Pointers to any of the above.
- Interfaces:
any/interface{}.