master
1const std = @import("std");
2const json = std.json;
3const testing = std.testing;
4
5const ArrayHashMap = @import("hashmap.zig").ArrayHashMap;
6
7const parseFromSlice = @import("static.zig").parseFromSlice;
8const parseFromSliceLeaky = @import("static.zig").parseFromSliceLeaky;
9const parseFromTokenSource = @import("static.zig").parseFromTokenSource;
10const parseFromValue = @import("static.zig").parseFromValue;
11const Value = @import("dynamic.zig").Value;
12
13const Scanner = @import("Scanner.zig");
14
15const T = struct {
16 i: i32,
17 s: []const u8,
18};
19
20test "parse json hashmap" {
21 const doc =
22 \\{
23 \\ "abc": {"i": 0, "s": "d"},
24 \\ "xyz": {"i": 1, "s": "w"}
25 \\}
26 ;
27 const parsed = try parseFromSlice(ArrayHashMap(T), testing.allocator, doc, .{});
28 defer parsed.deinit();
29
30 try testing.expectEqual(@as(usize, 2), parsed.value.map.count());
31 try testing.expectEqualStrings("d", parsed.value.map.get("abc").?.s);
32 try testing.expectEqual(@as(i32, 1), parsed.value.map.get("xyz").?.i);
33}
34
35test "parse json hashmap while streaming" {
36 const doc =
37 \\{
38 \\ "abc": {"i": 0, "s": "d"},
39 \\ "xyz": {"i": 1, "s": "w"}
40 \\}
41 ;
42 var stream: std.Io.Reader = .fixed(doc);
43 var json_reader: Scanner.Reader = .init(testing.allocator, &stream);
44
45 var parsed = try parseFromTokenSource(
46 ArrayHashMap(T),
47 testing.allocator,
48 &json_reader,
49 .{},
50 );
51 defer parsed.deinit();
52 // Deinit our reader to invalidate its buffer
53 json_reader.deinit();
54
55 try testing.expectEqual(@as(usize, 2), parsed.value.map.count());
56 try testing.expectEqualStrings("d", parsed.value.map.get("abc").?.s);
57 try testing.expectEqual(@as(i32, 1), parsed.value.map.get("xyz").?.i);
58}
59
60test "parse json hashmap duplicate fields" {
61 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
62 defer arena.deinit();
63
64 const doc =
65 \\{
66 \\ "abc": {"i": 0, "s": "d"},
67 \\ "abc": {"i": 1, "s": "w"}
68 \\}
69 ;
70
71 try testing.expectError(error.DuplicateField, parseFromSliceLeaky(ArrayHashMap(T), arena.allocator(), doc, .{
72 .duplicate_field_behavior = .@"error",
73 }));
74
75 const first = try parseFromSliceLeaky(ArrayHashMap(T), arena.allocator(), doc, .{
76 .duplicate_field_behavior = .use_first,
77 });
78 try testing.expectEqual(@as(usize, 1), first.map.count());
79 try testing.expectEqual(@as(i32, 0), first.map.get("abc").?.i);
80
81 const last = try parseFromSliceLeaky(ArrayHashMap(T), arena.allocator(), doc, .{
82 .duplicate_field_behavior = .use_last,
83 });
84 try testing.expectEqual(@as(usize, 1), last.map.count());
85 try testing.expectEqual(@as(i32, 1), last.map.get("abc").?.i);
86}
87
88test "stringify json hashmap" {
89 var value = ArrayHashMap(T){};
90 defer value.deinit(testing.allocator);
91 {
92 const doc = try json.Stringify.valueAlloc(testing.allocator, value, .{});
93 defer testing.allocator.free(doc);
94 try testing.expectEqualStrings("{}", doc);
95 }
96
97 try value.map.put(testing.allocator, "abc", .{ .i = 0, .s = "d" });
98 try value.map.put(testing.allocator, "xyz", .{ .i = 1, .s = "w" });
99
100 {
101 const doc = try json.Stringify.valueAlloc(testing.allocator, value, .{});
102 defer testing.allocator.free(doc);
103 try testing.expectEqualStrings(
104 \\{"abc":{"i":0,"s":"d"},"xyz":{"i":1,"s":"w"}}
105 , doc);
106 }
107
108 try testing.expect(value.map.swapRemove("abc"));
109 {
110 const doc = try json.Stringify.valueAlloc(testing.allocator, value, .{});
111 defer testing.allocator.free(doc);
112 try testing.expectEqualStrings(
113 \\{"xyz":{"i":1,"s":"w"}}
114 , doc);
115 }
116
117 try testing.expect(value.map.swapRemove("xyz"));
118 {
119 const doc = try json.Stringify.valueAlloc(testing.allocator, value, .{});
120 defer testing.allocator.free(doc);
121 try testing.expectEqualStrings("{}", doc);
122 }
123}
124
125test "stringify json hashmap whitespace" {
126 var value = ArrayHashMap(T){};
127 defer value.deinit(testing.allocator);
128 try value.map.put(testing.allocator, "abc", .{ .i = 0, .s = "d" });
129 try value.map.put(testing.allocator, "xyz", .{ .i = 1, .s = "w" });
130
131 {
132 const doc = try json.Stringify.valueAlloc(testing.allocator, value, .{ .whitespace = .indent_2 });
133 defer testing.allocator.free(doc);
134 try testing.expectEqualStrings(
135 \\{
136 \\ "abc": {
137 \\ "i": 0,
138 \\ "s": "d"
139 \\ },
140 \\ "xyz": {
141 \\ "i": 1,
142 \\ "s": "w"
143 \\ }
144 \\}
145 , doc);
146 }
147}
148
149test "json parse from value hashmap" {
150 const doc =
151 \\{
152 \\ "abc": {"i": 0, "s": "d"},
153 \\ "xyz": {"i": 1, "s": "w"}
154 \\}
155 ;
156 const parsed1 = try parseFromSlice(Value, testing.allocator, doc, .{});
157 defer parsed1.deinit();
158
159 const parsed2 = try parseFromValue(ArrayHashMap(T), testing.allocator, parsed1.value, .{});
160 defer parsed2.deinit();
161
162 try testing.expectEqualStrings("d", parsed2.value.map.get("abc").?.s);
163}