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}