voile.json5

JSON5 data module
This module provides functionality for working with JSON5 (JavaScript Object Notation ver.5) data. It includes definitions for various JSON5 data types, a builder for constructing JSON5 values, and methods for converting between JSON5 and native D types.
See Also: specs.json5.org
auto kind(string name, string value);
auto kind(string value);
auto kind(string value)();
Kind attribute
Attribute used for serialization of SumType. By adding this attribute to all aggregate types used in SumType, they become serializable.
auto converter(T1, T2)(void function(in T2, ref T1) @safe from, void function(in T1, ref T2) @safe to);
auto converter(T1, T2)(T1 function(in T2) @safe from, T2 function(in T1) @safe to);
auto converterString(T)(T function(string) @safe from, string function(in T) @safe to);
alias convStr = converterString(T)(T function(string) @safe from, string function(in T) @safe to);
auto converterBinary(T)(T function(immutable(ubyte)[]) @safe from, immutable(ubyte)[] function(in T) @safe to);
alias convBin = converterBinary(T)(T function(immutable(ubyte)[]) @safe from, immutable(ubyte)[] function(in T) @safe to);
Attribute converting method
@safe auto converterSysTime();
@safe auto converterDateTime();
@safe auto converterDate();
@safe auto converterTimeOfDay();
auto converterDuration();
auto converterUUID();
Special conveter attributes
enum CommentType: int;
auto comment(string cmt, CommentType type = CommentType.line);
Attribute of JSON5 Comment
auto stringFormat(bool singleQuote = false);
enum AttrJson5StringFormat singleQuotedStr;
Attribute of JSON5 string display format
auto integralFormat(bool positiveSign = false, bool hex = false);
Attribute of JSON5 integral number display format
auto floatingPointFormat(bool leadingDecimalPoint = false, bool tailingDecimalPoint = false, bool positiveSign = false, bool withExponent = false, size_t precision = 0);
Attribute of JSON5 floating point number display format
auto arrayFormat(bool tailingComma = false, bool singleLine = false);
enum AttrJson5ArrayFormat singleLineAry;
Attribute of JSON5 floating point number display format
auto objectFormat(bool tailingComma = false, bool singleLine = false);
enum AttrJson5ObjectFormat singleLineObj;
Attribute of JSON5 floating point number display format
enum QuotedStyle: int;
auto quotedKeyStyle(QuotedStyle style);
enum AttrJson5KeyQuotedStyle unquotedKey;
enum AttrJson5KeyQuotedStyle singleQuotedKey;
Attribute of JSON5 integral number display format
enum auto isBinary(T);
Determines if the type is binary
enum auto isSerializableTuple(T);
Determines if the Tuple can be serialized to JSON format
This template returns true if the type T meets the following conditions:
  • T is a Tuple
  • All members of the Tuple are serializable
Parameters:
T The type to check
Returns: true if T is a serializable tuple, false otherwise
enum auto isSerializableSumType(T);
Determines if the SumType can be serialized to JSON format
This template returns true if the type T meets the following conditions:
  • T is a SumType
  • All members of the SumType are serializable
  • All members of the SumType have the @kind attribute if they are aggregate types
  • There is at most one member of each of the following types: integral, floating point, boolean, string, binary, array, associative array
Parameters:
T The type to check
Returns: true if T is a serializable sum type, false otherwise
Examples: ditto
@kind("test1") struct Test1 { int value; }
@kind("test2") struct Test2 { int value; }
alias ST1 = SumType!(Test1, Test2);
static assert(allSatisfy!(hasKind, ST1.Types));
static assert(allSatisfy!(isSerializable, ST1.Types));

struct Test3 { int value; }
alias ST2 = SumType!(Test1, Test2, Test3);
static assert(!allSatisfy!(hasKind, ST2.Types));
static assert(!isSerializableSumType!ST2);
static assert(!isSerializableData!ST2);
static assert(!isSerializable!ST2);

alias ST3 = SumType!(int, ulong, string, immutable(ubyte)[]);
static assert(!isSerializableSumType!ST3);
static assert(!isSerializable!ST3);
template isSerializable(T)
Checks if a given type is serializable to JSON format.
This function determines whether a type can be serialized into the JSON (JavaScript Object Notation) format. JSON is a binary data serialization format which aims to provide a more compact representation compared to JSON.
Parameters:
T The type to check for serializability.
Returns: bool - true if the type is serializable to JSON, false otherwise.
template Json5DefaultAllocator()
struct JsonValue(Builder);
alias String = Builder.String;
alias Dictionary = Builder.Dictionary;
alias Array = Builder.Array;
struct JsonString;
String value;
bool singleQuoted;
struct JsonInteger;
long value;
bool positiveSign;
bool hex;
struct JsonUInteger;
ulong value;
bool positiveSign;
bool hex;
struct JsonFloatingPoint;
double value;
bool leadingDecimalPoint;
bool tailingDecimalPoint;
bool positiveSign;
bool withExponent;
size_t precision;
struct JsonKey;
String value;
QuotedStyle quotedStyle;
bool opEquals(in JsonKey lhs) const;
size_t toHash() const;
struct JsonObject;
Dictionary!(JsonKey, JsonValue) value;
bool tailingComma;
bool singleLine;
ref inout(Dictionary!(JsonKey, JsonValue).Item) opIndex()(size_t idx) inout;
ref inout(JsonValue) opIndex()(string key) inout;
struct JsonArray;
Array!JsonValue value;
bool tailingComma;
bool singleLine;
enum UndefinedValue;
alias JsonType = SumType!(UndefinedValue, JsonString, JsonInteger, JsonUInteger, JsonFloatingPoint, bool, JsonArray, JsonObject, typeof(null));
struct LineComment;
String value;
struct BlockComment;
Array!String value;
enum TrailingComment: LineComment;
alias Comment = SumType!(LineComment, BlockComment, TrailingComment);
enum Type: ubyte;
pure @system this(T)(T val, ref scope Builder builder) return;
pure ref @trusted JsonValue opAssign(T)(T value) return;
Assign operator
pure nothrow @nogc @safe Type type() const;
pure nothrow @nogc ref @trusted inout(JsonString) asString() inout;
pure nothrow @nogc ref @trusted inout(JsonInteger) asInteger() inout;
pure nothrow @nogc ref @trusted inout(JsonUInteger) asUInteger() inout;
pure nothrow @nogc ref @trusted inout(JsonFloatingPoint) asFloatingPoint() inout;
pure nothrow @nogc ref @trusted inout(bool) asBoolean() inout;
pure nothrow @nogc ref @trusted inout(JsonObject) asObject() inout;
pure nothrow @nogc ref @trusted inout(JsonArray) asArray() inout;
@safe T get(T)(lazy T defaultValue = T.init) inout;
@safe T getValue(T)(string key, lazy T defaultValue = T.init) inout;
@safe T getElement(T)(size_t idx, lazy T defaultValue = T.init) inout;
Get value as the given type
If the type conversion is not possible, return the given default value (or T.init if not given).
@safe size_t getCommentLength() const;
Get number of comments
void addComment(in char[] comment, CommentType type = CommentType.line);
@safe void addLineComment(in char[] comment);
@safe void addBlockComment(in char[] comment);
@safe void addBlockComment(in const(char)[][] commentLines);
@safe void addTrailingComment(in char[] comment);
Add a line comment/block comment/trailing comment
@safe void clearComment();
Clear all comments
@safe bool isLineComment(size_t idx) const;
@safe bool isBlockComment(size_t idx) const;
@safe bool isTrailingComment(size_t idx) const;
@safe bool hasTrailingComment() const;
Check if the comment at the given index is a line comment/block/trailing comment
ref @trusted inout(LineComment) asLineComment(size_t index) inout;
Reference comment as a line comment
ref @trusted inout(BlockComment) asBlockComment(size_t index) inout;
Reference comment as a block comment
ref @trusted inout(TrailingComment) asTrailingComment(size_t index) inout;
Reference comment as a block comment
@safe string getComment(size_t index) const;
@safe string getComments() const;
Get all comments as a single string
@safe StdJsonValue toStdJson() const;
struct Json5BuilderImpl(alias allocator = Json5DefaultAllocator);
alias JsonValue = .JsonValue!Json5Builder;
alias JsonType = JsonValue.Type;
alias JsonKey = JsonValue.JsonKey;
alias JsonString = JsonValue.JsonString;
alias JsonInteger = JsonValue.JsonInteger;
alias JsonUInteger = JsonValue.JsonUInteger;
alias JsonBoolean = bool;
alias JsonNullType = typeof(null);
alias JsonFloatingPoint = JsonValue.JsonFloatingPoint;
alias JsonObject = JsonValue.JsonObject;
alias JsonArray = JsonValue.JsonArray;
@trusted JsonValue make(T)(T v);
Create a JsonValue from a given value.
pure nothrow @nogc @safe void dispose(ref JsonValue v);
Dispose the given JsonValue
pure nothrow @trusted JsonValue undefinedValue();
Create a JsonValue of null.
pure nothrow @trusted JsonValue emptyArray();
Create a JsonValue of empty array.
pure nothrow @trusted JsonValue emptyObject();
Create a JsonValue of empty object.
pure nothrow @trusted JsonValue nullValue();
Create a JsonValue of null.
pure nothrow @safe JsonValue deepCopy(in JsonValue src);
Deep copy
@safe JsonValue parse(in char[] src);
Parse JSON string
enum JsonPrettyPrintOptions: uint;
Options for pretty-printing JSON
@safe void toPrettyString(OutputRange)(ref OutputRange dst, JsonValue value, in char[] indent = "\t", in char[] newline = "\n", JsonPrettyPrintOptions options = JsonPrettyPrintOptions.none);
Convert JSON value to pretty-printed string
@safe void update(T)(ref JsonValue dst, in T src) const;
Updates a JsonValue with struct data, preserving formatting as much as possible.
この関数はsrcの構造体データの値を使用して、dstのJsonValueの値部分のみを更新する目的で使用されます。 dstは必ずオブジェクトである必要があります。さもなくば、emptyObjectで上書きされます。 キーが存在しない場合は作成されます。 値の型が異なる場合は再作成されます。
@safe JsonValue serialize(T)(in T src);
Serialize a various data to JsonValue
The serialize function generates a JsonValue instance from the given data. The data type must be one of the following.
  • JsonValue
  • Integral type (int, uint, long, ulong, short, ushort, byte, ubyte)
  • Floating point type (float, double)
  • bool
  • string
  • binary (immutable(ubyte)[])
  • null
  • Array
    • Recursively serialized
  • AssociativeArray
    • Key allows string only
    • Recursively serialized
  • Tuple
    • Converted to a array type JsonValue
    • Recursively serialized
  • SumType
    • Converted to a object type JsonValue
      • All types have the @kind attribute
    • Recursively serialized
  • Aggregate type (struct, class, union): meets one of the following conditions
    • Composed of simple public member variables
      • Converted to a object type JsonValue
      • Recursively serialized
      • If the @ignore attribute is present, do not serialize
      • If the @ignoreIf attribute is present, do not serialize if the condition is met
      • If the @name attribute is present, use that name
      • If the @converter attribute is present, use that conversion proxy
      • If output formatting attributes are present, they will be used to decorate the output.
        • The @stringFormat attribute modifies string output.
        • The @integralFormat attribute modifies integral output.
        • The @floatingPointFormat attribute modifies floating-point output.
        • The @arrayFormat attribute modifies array output.
        • The @objectFormat attribute modifies object output.
        • The @quotedKeyStyle attribute modifies object key output.
    • toJson/fromJson methods, where fromJson is a static method
    • toString/fromString methods, where fromString is a static method
@safe void deserializeImpl(T)(in JsonValue src, ref T dst);
@safe bool deserialize(T)(in JsonValue src, ref T dst);
@safe T deserialize(T)(in JsonValue src);
Deserialize JSON value to specified structure
The deserialize function generates value from JsonValue instance. The data type must be one of the following.
  • JsonValue
  • Integral type (int, uint, long, ulong, short, ushort, byte, ubyte)
  • Floating point type (float, double)
  • bool
  • string
  • binary (immutable(ubyte)[])
  • null
  • Array
    • Recursively deserialized
  • AssociativeArray
    • Recursively deserialized
  • SumType
    • Converted from a map type JsonValue
      • All types have the @kind attribute
    • Recursively deserialized
  • Aggregate type (struct, class, union): meets one of the following conditions
    • Composed of simple public member variables
      • Converted to a map type JsonValue
      • Recursively deserialized
      • If the @ignore attribute is present, do not deserialize
      • If the @ignoreIf attribute is present, do not deserialize if the condition is met
      • If the @name attribute is present, use that name
      • If the @converter attribute is present, use that conversion proxy
      • If the @essential attribute is present, throw an exception if deserialization fails
    • toJson/fromJson methods, where fromJson is a static method
    • toBinary/fromBinary methods, where fromBinary is a static method
    • toRepresentation/fromRepresentation methods, where fromRepresentation is a static method
alias Json5Value = JsonValue!(Json5BuilderImpl!(Json5DefaultAllocator)).JsonValue;
alias Json5Type = JsonValue!(Json5BuilderImpl!(Json5DefaultAllocator)).JsonValue.Type;
alias Json5String = JsonValue!(Json5BuilderImpl!(Json5DefaultAllocator)).JsonValue.JsonString;
alias Json5UInteger = JsonValue!(Json5BuilderImpl!(Json5DefaultAllocator)).JsonValue.JsonUInteger;
alias Json5Integer = JsonValue!(Json5BuilderImpl!(Json5DefaultAllocator)).JsonValue.JsonInteger;
alias Json5FloatingPoint = JsonValue!(Json5BuilderImpl!(Json5DefaultAllocator)).JsonValue.JsonFloatingPoint;
alias Json5Object = JsonValue!(Json5BuilderImpl!(Json5DefaultAllocator)).JsonValue.JsonObject;
alias Json5Array = JsonValue!(Json5BuilderImpl!(Json5DefaultAllocator)).JsonValue.JsonArray;
alias Json5Options = Json5BuilderImpl!(Json5DefaultAllocator).Json5BuilderImpl.JsonPrettyPrintOptions;
@safe Json5Value makeJson(T)(in T val);
@safe Json5Value parseJson(in char[] str);
@safe Json5Value serializeToJson(T)(in T src);
@safe string serializeToJsonString(T)(in T src, in char[] indent = "\t", in char[] newline = "\n", Json5Options options = Json5Options.none);
@safe bool deserializeFromJson(T)(in Json5Value src, ref T dst);
@safe T deserializeFromJson(T)(in Json5Value src);
@safe bool deserializeFromJsonString(T)(in char[] src, ref T dst);
@safe T deserializeFromJsonString(T)(in char[] src);
Examples:
struct Data
{
	int x;
	int y;
}
auto dat1 = Data(1, 2);
auto str1 = dat1.serializeToJsonString();
assert(str1 == `
{
	"x": 1,
	"y": 2
}`.outdent.chompPrefix("\n"));
auto jv1 = parseJson(str1);
assert(jv1.getValue!int("x") == 1);
assert(jv1.getValue!int("y") == 2);

auto dat2 = deserializeFromJsonString!Data(`{ x: 1, y: 2 }`);
assert(dat1 == dat2);

auto jv2 = dat1.serializeToJson();
assert(jv2.getValue!int("x") == 1);
assert(jv2.getValue!int("y") == 2);

auto dat3 = deserializeFromJson!Data(makeJson(["x": 1, "y": 2]));
assert(dat3 == dat1);
Examples:
import std.math: isClose;
Json5Builder builder;
// 文字列
auto jv = builder.make("test");
assert(jv.get!string == "test");
assert(jv.get!uint == 0);
assert(jv.get!bool);
assert(jv.get!(typeof(null)) is null);
assert(jv.get!(string[string]) is null);
// 符号あり数値
jv = builder.make(10);
assert(jv.get!int == 10);
assert(jv.get!uint == 10);
assert(jv.get!float.isClose(10));
assert(jv.get!string == "");
assert(jv.get!bool);
assert(jv.get!(typeof(null)) is null);
assert(jv.get!(string[string]) is null);
// 符号なし整数
jv = builder.make(11U);
assert(jv.get!int == 11);
assert(jv.get!uint == 11);
assert(jv.get!float.isClose(11));
assert(jv.get!string == "");
assert(jv.get!bool);
assert(jv.get!(typeof(null)) is null);
assert(jv.get!(string[string]) is null);
// 浮動小数点数
jv = builder.make(12.3);
assert(jv.get!float.isClose(12.3));
assert(jv.get!int == 12);
assert(jv.get!uint == 12);
assert(jv.get!string == "");
assert(jv.get!(typeof(null)) is null);
assert(jv.get!(string[string]) is null);
// 論理値
jv = builder.make(true);
assert(jv.get!bool);
jv = builder.make(false);
assert(!jv.get!bool);
// NULL
jv = builder.make(null);
assert(jv.get!(typeof(null)) is null);
// 配列
jv = builder.make(["test1", "test2"]);
assert(jv.get!(string[]).length == 2);
assert(jv.get!(string[]) == ["test1", "test2"]);
// 連想配列
jv = builder.make(["test": "value"]);
assert(jv.get!(string[string])["test"] == "value");
jv = builder.make(["test2": 42]);
assert(jv.get!(int[string])["test2"] == 42);
jv = builder.make(["test3": builder.make(true)]);
assert(jv.get!(bool[string])["test3"] == true);

jv = builder.make(cast(const string)"test");
assert(jv.get!string == "test");

jv = builder.make(cast(const ubyte[])"\x01\x02\x03");
assert(jv.get!(ubyte[]) == [1, 2, 3]);