pub fn validate(allocator: Allocator, s: []const u8) Allocator.Error!boolScan the input and check for malformed JSON. On SyntaxError or UnexpectedEndOfInput, returns false. Returns any errors from the allocator as-is, which is unlikely, but can be caused by extreme nesting depth in the input.
pub fn isNumberFormattedLikeAnInteger(value: []const u8) boolFor the slice you get from a Token.number or Token.allocated_number, this function returns true if the number doesn't contain any fraction or exponent components, and is not -0. Note, the numeric value encoded by the value may still be an integer, such as 1.0. This function is meant to give a hint about whether integer parsing or float parsing should be used on the value. This function will not give meaningful results on non-numeric input.
pub fn parseFromSlice(comptime T: type, allocator: Allocator, s: []const u8, options: ParseOptions) ParseError(Scanner)!Parsed(T)Parses the json document from s and returns the result packaged in a std.json.Parsed. You must call deinit() of the returned object to clean up allocated resources. If you are using a std.heap.ArenaAllocator or similar, consider calling parseFromSliceLeaky instead. Note that error.BufferUnderrun is not actually possible to return from this function.
pub fn parseFromSliceLeaky(comptime T: type, allocator: Allocator, s: []const u8, options: ParseOptions) ParseError(Scanner)!TParses the json document from s and returns the result. Allocations made during this operation are not carefully tracked and may not be possible to individually clean up. It is recommended to use a std.heap.ArenaAllocator or similar.
pub fn parseFromTokenSource(comptime T: type, allocator: Allocator, scanner_or_reader: anytype, options: ParseOptions) ParseError(@TypeOf(scanner_or_reader .*))!Parsed(T)scanner_or_reader must be either a *std.json.Scanner with complete input or a *std.json.Reader. Note that error.BufferUnderrun is not actually possible to return from this function.
pub fn parseFromTokenSourceLeaky(comptime T: type, allocator: Allocator, scanner_or_reader: anytype, options: ParseOptions) ParseError(@TypeOf(scanner_or_reader .*))!Tscanner_or_reader must be either a *std.json.Scanner with complete input or a *std.json.Reader. Allocations made during this operation are not carefully tracked and may not be possible to individually clean up. It is recommended to use a std.heap.ArenaAllocator or similar.
pub fn innerParse(comptime T: type, allocator: Allocator, source: anytype, options: ParseOptions) ParseError(@TypeOf(source .*))!TThis is an internal function called recursively during the implementation of parseFromTokenSourceLeaky and similar. It is exposed primarily to enable custom jsonParse() methods to call back into the parseFrom* system, such as if you're implementing a custom container of type T; you can call innerParse(T, ...) for each of the container's items. Note that null fields are not allowed on the options when calling this function. (The options you get in your jsonParse method has no null fields.)
pub fn parseFromValue(comptime T: type, allocator: Allocator, source: Value, options: ParseOptions) ParseFromValueError!Parsed(T)Like parseFromSlice, but the input is an already-parsed std.json.Value object. Only options.ignore_unknown_fields is used from options.
pub fn parseFromValueLeaky(comptime T: type, allocator: Allocator, source: Value, options: ParseOptions) ParseFromValueError!Tpub fn innerParseFromValue(comptime T: type, allocator: Allocator, source: Value, options: ParseOptions) ParseFromValueError!TThis is an internal function called recursively during the implementation of parseFromValueLeaky. It is exposed primarily to enable custom jsonParseFromValue() methods to call back into the parseFromValue* system, such as if you're implementing a custom container of type T; you can call innerParseFromValue(T, ...) for each of the container's items.
pub fn fmt(value: anytype, options: Stringify.Options) Formatter(@TypeOf(value))Returns a formatter that formats the given value using stringify.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140//! JSON parsing and stringification conforming to RFC 8259. https://datatracker.ietf.org/doc/html/rfc8259
//!
//! The low-level `Scanner` API produces `Token`s from an input slice or successive slices of inputs,
//! The `Reader` API connects a `std.Io.Reader` to a `Scanner`.
//!
//! The high-level `parseFromSlice` and `parseFromTokenSource` deserialize a JSON document into a Zig type.
//! Parse into a dynamically-typed `Value` to load any JSON value for runtime inspection.
//!
//! The low-level `writeStream` emits syntax-conformant JSON tokens to a `std.Io.Writer`.
//! The high-level `stringify` serializes a Zig or `Value` type into JSON.
const builtin = @import("builtin");
const std = @import("std");
const testing = std.testing;
test Scanner {
var scanner = Scanner.initCompleteInput(testing.allocator, "{\"foo\": 123}\n");
defer scanner.deinit();
try testing.expectEqual(Token.object_begin, try scanner.next());
try testing.expectEqualSlices(u8, "foo", (try scanner.next()).string);
try testing.expectEqualSlices(u8, "123", (try scanner.next()).number);
try testing.expectEqual(Token.object_end, try scanner.next());
try testing.expectEqual(Token.end_of_document, try scanner.next());
}
test parseFromSlice {
var parsed_str = try parseFromSlice([]const u8, testing.allocator, "\"a\\u0020b\"", .{});
defer parsed_str.deinit();
try testing.expectEqualSlices(u8, "a b", parsed_str.value);
const T = struct { a: i32 = -1, b: [2]u8 };
var parsed_struct = try parseFromSlice(T, testing.allocator, "{\"b\":\"xy\"}", .{});
defer parsed_struct.deinit();
try testing.expectEqual(@as(i32, -1), parsed_struct.value.a); // default value
try testing.expectEqualSlices(u8, "xy", parsed_struct.value.b[0..]);
}
test Value {
var parsed = try parseFromSlice(Value, testing.allocator, "{\"anything\": \"goes\"}", .{});
defer parsed.deinit();
try testing.expectEqualSlices(u8, "goes", parsed.value.object.get("anything").?.string);
}
test Stringify {
var out: std.Io.Writer.Allocating = .init(testing.allocator);
var write_stream: Stringify = .{
.writer = &out.writer,
.options = .{ .whitespace = .indent_2 },
};
defer out.deinit();
try write_stream.beginObject();
try write_stream.objectField("foo");
try write_stream.write(123);
try write_stream.endObject();
const expected =
\\{
\\ "foo": 123
\\}
;
try testing.expectEqualSlices(u8, expected, out.written());
}
pub const ObjectMap = @import("json/dynamic.zig").ObjectMap;
pub const Array = @import("json/dynamic.zig").Array;
pub const Value = @import("json/dynamic.zig").Value;
pub const ArrayHashMap = @import("json/hashmap.zig").ArrayHashMap;
pub const Scanner = @import("json/Scanner.zig");
pub const validate = Scanner.validate;
pub const Error = Scanner.Error;
pub const default_buffer_size = Scanner.default_buffer_size;
pub const Token = Scanner.Token;
pub const TokenType = Scanner.TokenType;
pub const Diagnostics = Scanner.Diagnostics;
pub const AllocWhen = Scanner.AllocWhen;
pub const default_max_value_len = Scanner.default_max_value_len;
pub const Reader = Scanner.Reader;
pub const isNumberFormattedLikeAnInteger = Scanner.isNumberFormattedLikeAnInteger;
pub const ParseOptions = @import("json/static.zig").ParseOptions;
pub const Parsed = @import("json/static.zig").Parsed;
pub const parseFromSlice = @import("json/static.zig").parseFromSlice;
pub const parseFromSliceLeaky = @import("json/static.zig").parseFromSliceLeaky;
pub const parseFromTokenSource = @import("json/static.zig").parseFromTokenSource;
pub const parseFromTokenSourceLeaky = @import("json/static.zig").parseFromTokenSourceLeaky;
pub const innerParse = @import("json/static.zig").innerParse;
pub const parseFromValue = @import("json/static.zig").parseFromValue;
pub const parseFromValueLeaky = @import("json/static.zig").parseFromValueLeaky;
pub const innerParseFromValue = @import("json/static.zig").innerParseFromValue;
pub const ParseError = @import("json/static.zig").ParseError;
pub const ParseFromValueError = @import("json/static.zig").ParseFromValueError;
pub const Stringify = @import("json/Stringify.zig");
/// Returns a formatter that formats the given value using stringify.
pub fn fmt(value: anytype, options: Stringify.Options) Formatter(@TypeOf(value)) {
return Formatter(@TypeOf(value)){ .value = value, .options = options };
}
test fmt {
const expectFmt = std.testing.expectFmt;
try expectFmt("123", "{f}", .{fmt(@as(u32, 123), .{})});
try expectFmt(
\\{"num":927,"msg":"hello","sub":{"mybool":true}}
, "{f}", .{fmt(struct {
num: u32,
msg: []const u8,
sub: struct {
mybool: bool,
},
}{
.num = 927,
.msg = "hello",
.sub = .{ .mybool = true },
}, .{})});
}
/// Formats the given value using stringify.
pub fn Formatter(comptime T: type) type {
return struct {
value: T,
options: Stringify.Options,
pub fn format(self: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void {
try Stringify.value(self.value, self.options, writer);
}
};
}
test {
_ = @import("json/test.zig");
_ = Scanner;
_ = @import("json/dynamic.zig");
_ = @import("json/hashmap.zig");
_ = @import("json/static.zig");
_ = Stringify;
_ = @import("json/JSONTestSuite_test.zig");
}
JSON parsing and stringification conforming to RFC 8259. https://datatracker.ietf.org/doc/html/rfc8259
The low-level
ScannerAPI producesTokens from an input slice or successive slices of inputs, TheReaderAPI connects astd.Io.Readerto aScanner.The high-level
parseFromSliceandparseFromTokenSourcedeserialize a JSON document into a Zig type. Parse into a dynamically-typedValueto load any JSON value for runtime inspection.The low-level
writeStreamemits syntax-conformant JSON tokens to astd.Io.Writer. The high-levelstringifyserializes a Zig orValuetype into JSON.