Public beta — not for production use. Data may be wiped at any time. Questions? Contact us.
A
Axiom
/Marketplace/christiangeorgelucas/ion-tools
Sign in

christiangeorgelucas/ion-tools

v0.1.0Go

The ion-tools package provides composable Axiom nodes for working with Amazon Ion, a self-describing data format used by various AWS services. It facilitates operations such as transcoding between text and binary formats, converting Ion to JSON (and vice versa), validating Ion documents, and inspecting their structure, making it essential for developers working with Ion data in Go.

amazon-iondata-formatgojson-conversionvalidationpretty-printingtype-inspectiontranscoding

Use cases

  • Convert Ion documents to and from JSON for interoperability
  • Validate the structure of Ion documents before processing
  • Inspect and analyze the types and annotations in Ion data
  • Pretty-print Ion documents for better readability
  • Extract symbol tables from Ion documents for efficient encoding

Nodes (8)

BinaryToTextunary
IonBinary·IonText

The BinaryToText node converts an Ion document from its compact binary encoding to a human-readable text encoding, preserving all top-level values, containers, field names, and annotations. It serves as the inverse operation of the TextToBinary node.

View source
package nodes

import (
	"context"

	"christiangeorgelucas/ion-tools/axiom"
	gen "christiangeorgelucas/ion-tools/gen"
)

// Convert an Ion document from its compact binary encoding to its text
// encoding. Every top-level value, container, field name, and annotation in
// the input is preserved exactly — only the byte-level encoding changes.
func BinaryToText(ctx context.Context, ax axiom.Context, input *gen.IonBinary) (*gen.IonText, error) {
	if input == nil || len(input.Data) == 0 {
		return &gen.IonText{Error: "data is required"}, nil
	}

	text, err := ionBinaryToText(input.Data)
	if err != nil {
		return &gen.IonText{Error: err.Error()}, nil
	}
	return &gen.IonText{Text: text}, nil
}
ExtractSymbolTableunary
IonInput·SymbolTableInfo

The ExtractSymbolTable node processes an Ion document to extract its local symbol table, which maps small integer symbol IDs to their corresponding text. It validates the document to ensure that any malformed Ion is reported as an error, providing a reliable symbol table extraction.

View source
package nodes

import (
	"context"

	"christiangeorgelucas/ion-tools/axiom"
	gen "christiangeorgelucas/ion-tools/gen"
)

// Extract the local symbol table an Ion document (text or binary,
// auto-detected) carries — the table mapping small integer symbol IDs to
// their text, which is what lets Ion binary encode field names, annotation
// names, and symbol values compactly. Most informative for Ion binary
// input, which always carries one; plain Ion text generally returns an
// empty result unless it explicitly declares a $ion_symbol_table struct —
// that is expected behavior, not an error.
func ExtractSymbolTable(ctx context.Context, ax axiom.Context, input *gen.IonInput) (*gen.SymbolTableInfo, error) {
	if input == nil || len(input.Data) == 0 {
		return &gen.SymbolTableInfo{Error: "data is required"}, nil
	}

	info, err := extractSymbolTableFromIon(input.Data)
	if err != nil {
		return &gen.SymbolTableInfo{Error: err.Error()}, nil
	}
	return info, nil
}
InspectStructureunary
IonInput·StructureReport

The InspectStructure node analyzes an Ion document, providing a detailed structural summary that includes a type tree for each top-level value, distinct Ion types and annotations, maximum container nesting depth, and total value count. This node highlights the unique features of Ion, such as type annotations and a richer type system, distinguishing it from traditional JSON inspection.

View source
package nodes

import (
	"context"

	"christiangeorgelucas/ion-tools/axiom"
	gen "christiangeorgelucas/ion-tools/gen"
)

// Produce a structural, type-aware summary of an Ion document (text or
// binary, auto-detected): a type tree for each top-level value, the
// distinct Ion types and annotations used anywhere in the document, the
// maximum container nesting depth, and the total value count. This
// surfaces what makes Ion inspection different from inspecting JSON — Ion
// values can carry type annotations (e.g. `meters::5`) and a richer type
// system (timestamp, decimal, symbol, blob, clob, sexp) that this node
// reports explicitly rather than collapsing into a generic "object"/"array".
func InspectStructure(ctx context.Context, ax axiom.Context, input *gen.IonInput) (*gen.StructureReport, error) {
	if input == nil || len(input.Data) == 0 {
		return &gen.StructureReport{Error: "data is required"}, nil
	}

	report, err := inspectIon(input.Data)
	if err != nil {
		return &gen.StructureReport{Error: err.Error()}, nil
	}
	return report, nil
}
IonToJsonunary
IonInput·JsonDoc

The IonToJson node converts Ion documents, whether text or binary, into JSON format while intentionally losing some data fidelity due to JSON's simpler type system. It handles various Ion types by transforming them into JSON-compatible representations, ensuring that the output is structured correctly based on the number of top-level Ion values.

View source
package nodes

import (
	"context"

	"christiangeorgelucas/ion-tools/axiom"
	gen "christiangeorgelucas/ion-tools/gen"
)

// Convert an Ion document (text or binary, auto-detected) to JSON text. This
// is intentionally LOSSY: annotations are dropped, symbols become strings,
// decimals and timestamps become JSON strings (not numbers) holding their
// exact Ion text form, and blobs/clobs become base64 strings — see the
// ionutil.go helper's doc comment for the full, honest list of what does not
// survive. If the document has exactly one top-level Ion value, its direct
// JSON translation is returned; otherwise (zero or multiple top-level
// values) the result is a JSON array of them, in document order.
func IonToJson(ctx context.Context, ax axiom.Context, input *gen.IonInput) (*gen.JsonDoc, error) {
	if input == nil || len(input.Data) == 0 {
		return &gen.JsonDoc{Error: "data is required"}, nil
	}

	j, err := ionToJSON(input.Data)
	if err != nil {
		return &gen.JsonDoc{Error: err.Error()}, nil
	}
	return &gen.JsonDoc{Json: j}, nil
}
JsonToIonunary
JsonDoc·IonText

The JsonToIon node converts a JSON document into Ion text format, ensuring that the structure and data types are preserved according to Ion specifications. It handles JSON's null, boolean, number, string, array, and object types, while maintaining the order of fields and managing integer overflows appropriately.

View source
package nodes

import (
	"context"

	"christiangeorgelucas/ion-tools/axiom"
	gen "christiangeorgelucas/ion-tools/gen"
)

// Convert a JSON document to Ion text. JSON's null/bool/number/string/
// array/object map onto Ion's null/bool/int-or-float/string/list/struct,
// preserving field order. JSON has no annotation, symbol, decimal,
// timestamp, blob, or clob concept, so this never produces one — chain with
// TextToBinary if you need Ion binary output instead of text.
func JsonToIon(ctx context.Context, ax axiom.Context, input *gen.JsonDoc) (*gen.IonText, error) {
	if input == nil || input.Json == "" {
		return &gen.IonText{Error: "json is required"}, nil
	}

	text, err := jsonToIonText(input.Json)
	if err != nil {
		return &gen.IonText{Error: err.Error()}, nil
	}
	return &gen.IonText{Text: text}, nil
}
PrettyPrintunary
IonInput·IonText

The PrettyPrint node re-serializes an Ion document, whether in text or binary format, into a human-readable Ion text format with proper indentation and line breaks for better readability. It ensures that each value or field is displayed on a separate line, making it easier to navigate nested structures.

View source
package nodes

import (
	"context"

	"christiangeorgelucas/ion-tools/axiom"
	gen "christiangeorgelucas/ion-tools/gen"
)

// Re-serialize an Ion document (text or binary, auto-detected) as indented,
// human-readable Ion text — one value/field per line with nested containers
// indented, unlike the compact single-line form TextToBinary's inverse
// (BinaryToText) produces.
func PrettyPrint(ctx context.Context, ax axiom.Context, input *gen.IonInput) (*gen.IonText, error) {
	if input == nil || len(input.Data) == 0 {
		return &gen.IonText{Error: "data is required"}, nil
	}

	text, err := ionPrettyPrint(input.Data)
	if err != nil {
		return &gen.IonText{Error: err.Error()}, nil
	}
	return &gen.IonText{Text: text}, nil
}
TextToBinaryunary
IonText·IonBinary

The TextToBinary node converts an Ion document from its human-readable text encoding to its compact binary encoding, preserving all top-level values, containers, field names, and annotations without any data alteration. This process results in a byte-level re-encoding that begins with the version marker 0xE0 0x01 0x00 0xEA.

View source
package nodes

import (
	"context"

	"christiangeorgelucas/ion-tools/axiom"
	gen "christiangeorgelucas/ion-tools/gen"
)

// Convert an Ion document from its text encoding to its compact binary
// encoding (the form starting with the 0xE0 0x01 0x00 0xEA version marker).
// Every top-level value, container, field name, and annotation in the input
// is preserved exactly — only the byte-level encoding changes.
func TextToBinary(ctx context.Context, ax axiom.Context, input *gen.IonText) (*gen.IonBinary, error) {
	if input == nil || input.Text == "" {
		return &gen.IonBinary{Error: "text is required"}, nil
	}

	data, err := ionTextToBinary(input.Text)
	if err != nil {
		return &gen.IonBinary{Error: err.Error()}, nil
	}
	return &gen.IonBinary{Data: data}, nil
}
ValidateIonunary
IonInput·ValidationResult

The ValidateIon node checks the well-formedness of an Ion document, automatically detecting whether it is text or binary. It fully materializes every top-level value and descends into containers to catch any parse errors early in the process.

View source
package nodes

import (
	"context"

	"christiangeorgelucas/ion-tools/axiom"
	gen "christiangeorgelucas/ion-tools/gen"
)

// Check whether an Ion document (text or binary, auto-detected) is
// well-formed. Parses every top-level value fully (including descending
// into every container) so a deferred parse error — a malformed decimal, an
// invalid UTF-8 string, an out-of-range timestamp — is caught here rather
// than surfacing later in a different node. valid is false and error
// explains why on any parse failure; value_count reports how many top-level
// values were successfully read before validation concluded (the full count
// when valid).
func ValidateIon(ctx context.Context, ax axiom.Context, input *gen.IonInput) (*gen.ValidationResult, error) {
	if input == nil || len(input.Data) == 0 {
		return &gen.ValidationResult{Valid: false, Error: "data is required"}, nil
	}

	return validateIonData(input.Data), nil
}

Messages (8)

Download .proto
IonBinary
data:bytes
error:string
IonInput
data:bytes
IonText
text:string

The Ion text output generated from the input JSON, if conversion is successful.

error:string

An error message indicating any issues encountered during the conversion process.

JsonDoc
json:string
error:string

An error message indicating any issues encountered during the conversion process.

StructureNode
ion_type:string
is_null:bool
annotations:[]string
field_name:string
children:[]StructureNode
StructureReport
top_level_values:[]StructureNode
ion_types_present:[]string
annotations_used:[]string
max_depth:int32
value_count:int32
error:string

A string that indicates any errors encountered during the inspection process, such as malformed input.

SymbolTableInfo
symbols:[]string
imports:[]string
max_id:int32
error:string
ValidationResult
valid:bool
error:string
value_count:int32

Use as a tool in any AI agent

christiangeorgelucas/ion-tools is callable as a tool from any MCP client (Claude, Cursor, or your own agent) via Axiom's hosted MCP server — no install, no download. Add the server, then your agent can search and invoke it, or pin it as a typed tool.

claude mcp add --transport http axiom https://api.axiomide.com/mcp --header "Authorization: Bearer YOUR_AXIOM_API_KEY"

Replace YOUR_AXIOM_API_KEY with a key you create in Console → API Keys.

MCP server setup & other clients →

Use this package

Sign in to import christiangeorgelucas/ion-tools into the graph editor — drop it into a flow and hit run. Or call it directly via the API Reference with your API key.

Sign in to useOpen editor

Stats

Error rate (1h)0.0%
Back to marketplace