//! 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 testing = @import("std").testing; const ArrayList = @import("std").ArrayList; 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 writeStream { var out = ArrayList(u8).init(testing.allocator); defer out.deinit(); var write_stream = writeStream(out.writer(), .{ .whitespace = .indent_2 }); defer write_stream.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.items); } test stringify { var out = ArrayList(u8).init(testing.allocator); defer out.deinit(); const T = struct { a: i32, b: []const u8 }; try stringify(T{ .a = 123, .b = "xy" }, .{}, out.writer()); try testing.expectEqualSlices(u8, "{\"a\":123,\"b\":\"xy\"}", out.items); } 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 validate = @import("json/scanner.zig").validate; pub const Error = @import("json/scanner.zig").Error; pub const reader = @import("json/scanner.zig").reader; pub const default_buffer_size = @import("json/scanner.zig").default_buffer_size; pub const Token = @import("json/scanner.zig").Token; pub const TokenType = @import("json/scanner.zig").TokenType; pub const Diagnostics = @import("json/scanner.zig").Diagnostics; pub const AllocWhen = @import("json/scanner.zig").AllocWhen; pub const default_max_value_len = @import("json/scanner.zig").default_max_value_len; pub const Reader = @import("json/scanner.zig").Reader; pub const Scanner = @import("json/scanner.zig").Scanner; pub const isNumberFormattedLikeAnInteger = @import("json/scanner.zig").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 StringifyOptions = @import("json/stringify.zig").StringifyOptions; pub const stringify = @import("json/stringify.zig").stringify; pub const stringifyMaxDepth = @import("json/stringify.zig").stringifyMaxDepth; pub const stringifyArbitraryDepth = @import("json/stringify.zig").stringifyArbitraryDepth; pub const stringifyAlloc = @import("json/stringify.zig").stringifyAlloc; pub const writeStream = @import("json/stringify.zig").writeStream; pub const writeStreamMaxDepth = @import("json/stringify.zig").writeStreamMaxDepth; pub const writeStreamArbitraryDepth = @import("json/stringify.zig").writeStreamArbitraryDepth; pub const WriteStream = @import("json/stringify.zig").WriteStream; pub const encodeJsonString = @import("json/stringify.zig").encodeJsonString; pub const encodeJsonStringChars = @import("json/stringify.zig").encodeJsonStringChars; pub const Formatter = @import("json/fmt.zig").Formatter; pub const fmt = @import("json/fmt.zig").fmt; // Deprecations pub const parse = @compileError("Deprecated; use parseFromSlice() or parseFromTokenSource() instead."); pub const parseFree = @compileError("Deprecated; call Parsed(T).deinit() instead."); pub const Parser = @compileError("Deprecated; use parseFromSlice(Value) or parseFromTokenSource(Value) instead."); pub const ValueTree = @compileError("Deprecated; use Parsed(Value) instead."); pub const StreamingParser = @compileError("Deprecated; use json.Scanner or json.Reader instead."); pub const TokenStream = @compileError("Deprecated; use json.Scanner or json.Reader instead."); test { _ = @import("json/test.zig"); _ = @import("json/scanner.zig"); _ = @import("json/dynamic.zig"); _ = @import("json/hashmap.zig"); _ = @import("json/static.zig"); _ = @import("json/stringify.zig"); _ = @import("json/JSONTestSuite_test.zig"); }