NAME

SION - a serialization format a little more expressive than JSON

VERSION

Version 0.01

SYNOPSIS

use SION;    # exports encode_sion() and decode_sion()

# functional interface: SION text is UTF-8 octets
my $data = decode_sion($sion_text);
my $sion = encode_sion($data);

# OO interface, a la JSON::PP: SION text is a character string
# unless ->utf8 is enabled
my $codec = SION->new->canonical->pretty;
$sion = $codec->encode($data);
$data = $codec->decode($sion);

DESCRIPTION

SION is a data serialization format whose origin is Swift literals, just like JSON's origin is JavaScript literals. It is a little more expressive than JSON:

[
    "nil":      nil,                // nil is allowed
    "bool":     true,
    "int":      -42,               // Int is distinguished from Double
    "double":   0x1.518f5c28f5c29p+5,   // C99 hexadecimal notation
    "string":   "漢字、カタカナ、ひらがなの入ったstring😇",
    "array":    [nil, true, 1, 1.0, "one", [1], ["one":1.0]],
    "dictionary": ["nil":nil, "array":[], "object":[:]],
    "data":     .Data("R0lGODlh"), // binary data in Base64
    "date":     .Date(0x0p+0),     // date in seconds since epoch
    "ext":      .Ext("1NTU"),      // msgpack-style extension
    1:          "non-string keys are also allowed", // comments, too!
]

This module implements a SION encoder/decoder for Perl with an interface modeled after JSON::PP.

MAPPING

SION            Perl
--------------- ------------------------------------------
nil             undef
true/false      JSON::PP::true / JSON::PP::false
Int             integer (IV)
Double          floating point number (NV)
String          character string (decoded UTF-8 string)
Data            byte string (raw octets); SION::Data to force
Date            SION::Date object
Ext             SION::Ext object
Array           ARRAY reference
Dictionary      HASH reference
booleans

Booleans are handled exactly like JSON::PP: true and false decode to JSON::PP::true and JSON::PP::false. On encoding, JSON::PP::Boolean objects, \1 and \0, and (on perl 5.36+) native booleans like !!1 all encode to true/false.

Int vs Double

Like JSON::PP, this module looks at the internal flags of a scalar to tell an integer from a floating point number: 1 encodes to 1 while 1.0 encodes to 0x1p+0. Doubles are always encoded in C99 hexadecimal floating point notation via sprintf '%a', which is lossless; nan, inf and -inf are also supported. On decoding, Int becomes an IV and Double becomes an NV, so the distinction round-trips.

String vs Data

SION strings are utf-8 strings and SION data are byte strings. On decoding, a String becomes a perl character string (decoded text) while .Data("...") becomes a plain byte string of raw octets. On encoding, a scalar with the UTF8 flag set, or a byte string which is valid UTF-8 (including plain ASCII), encodes as a String; a byte string which is not valid UTF-8 encodes as .Data("...") in Base64. To force a valid-UTF-8 byte string to encode as Data, wrap it in SION::Data->new($bytes).

dates

.Date(n) decodes to a SION::Date object where n is seconds since epoch (may be fractional). $date->epoch returns it; the object also numifies to it. On encoding, SION::Date objects and any object with an epoch method (Time::Piece, DateTime, Time::Moment, ...) encode as .Date(...).

dictionaries

SION allows non-string dictionary keys. Since perl hash keys are strings, non-string keys are stringified on decoding (numbers via plain stringification, nil/true/false as those words, anything else via its canonical SION encoding). On encoding, hash keys are always emitted as Strings.

FUNCTIONS

encode_sion

$sion_octets = encode_sion($data);

Encodes a perl data structure to UTF-8 encoded SION text. Equivalent to SION->new->utf8->encode($data). Exported by default.

decode_sion

$data = decode_sion($sion_octets);

Decodes UTF-8 encoded SION text to a perl data structure. Equivalent to SION->new->utf8->decode($sion_octets). Exported by default.

true

false

Return JSON::PP::true and JSON::PP::false respectively. Exportable on demand.

is_bool

$bool = SION::is_bool($value);

Returns true if $value is a boolean: a JSON::PP::Boolean object or (on perl 5.36+) a native boolean. Exportable on demand.

METHODS

The mutators below return the object itself so that they can be chained, just like JSON::PP:

my $sion = SION->new->utf8->canonical->pretty->encode($data);

Each foo mutator has a corresponding get_foo accessor.

new

$codec = SION->new;

Creates a new encoder/decoder object with the default settings: non-utf8, non-ascii, compact output, non-canonical, allow_nonref enabled, max_depth of 512.

encode

$sion_text = $codec->encode($data);

Encodes a perl data structure to SION text.

decode

$data = $codec->decode($sion_text);

Decodes SION text to a perl data structure. Croaks on malformed input with the character offset of the error, a la JSON::PP.

utf8

$codec = $codec->utf8([$enable]);

If enabled, encode returns UTF-8 encoded octets and decode expects UTF-8 encoded octets. If disabled (default), SION text is a perl character string.

ascii

$codec = $codec->ascii([$enable]);

If enabled, encode escapes all non-ASCII characters in strings as \uXXXX (using surrogate pairs beyond U+FFFF) so the output is pure ASCII.

pretty

$codec = $codec->pretty([$enable]);

Enables (or disables) indent, space_before and space_after at once, for human readable output.

indent

indent_length

space_before

space_after

Fine-grained control over the output format, a la JSON::PP: indent puts each element on its own line indented by indent_length (default 4) spaces per level; space_before/space_after add a space before/after the : of dictionary entries.

canonical

$codec = $codec->canonical([$enable]);

If enabled, dictionary keys are sorted, so the output is deterministic.

allow_nonref

$codec = $codec->allow_nonref([$enable]);

If disabled, encode/decode croak unless the top level value is an array or dictionary. Enabled by default, following JSON::PP 4.x / RFC 8259.

allow_blessed

convert_blessed

Like JSON::PP: if convert_blessed is enabled, a blessed object with a TO_SION method is encoded as the value that method returns; otherwise, if allow_blessed is enabled, unknown blessed objects encode as nil; otherwise they croak. (JSON::PP::Boolean, SION::Date, SION::Data, SION::Ext and objects with an epoch method are always handled natively.)

max_depth

$codec = $codec->max_depth($n);

Maximum nesting level (default 512) accepted while encoding or decoding; exceeding it croaks.

HELPER CLASSES

SION::Date
my $date = SION::Date->new($epoch);  # seconds since epoch, may be fractional
$date->epoch;                        # get it back
0 + $date;                           # numifies to epoch
SION::Data
my $data = SION::Data->new($bytes);  # force encoding as .Data(...)
$data->data;                         # the byte string
SION::Ext
my $ext = SION::Ext->new($bytes);    # decoded from / encodes to .Ext(...)
$ext->data;                          # the byte string

SEE ALSO

https://dankogai.github.io/SION/, https://github.com/dankogai/swift-sion, https://github.com/dankogai/js-sion, JSON::PP

AUTHOR

Dan Kogai <dankogai@cpan.org>

BUGS

Please report any bugs or feature requests to bug-sion at rt.cpan.org, or through the web interface at https://rt.cpan.org/NoAuth/ReportBug.html?Queue=SION. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

perldoc SION

You can also look for information at:

LICENSE AND COPYRIGHT

This software is Copyright (c) 2026 by Dan Kogai <dankogai@cpan.org>.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)