diff --git a/lib/std/json/hashmap.zig b/lib/std/json/hashmap.zig index 7b66a95c87..b40fb5e4c7 100644 --- a/lib/std/json/hashmap.zig +++ b/lib/std/json/hashmap.zig @@ -24,15 +24,10 @@ pub fn ArrayHashMap(comptime T: type) type { if (.object_begin != try source.next()) return error.UnexpectedToken; while (true) { - const token = try source.nextAlloc(allocator, .alloc_if_needed); + const token = try source.nextAlloc(allocator, options.allocate.?); switch (token) { inline .string, .allocated_string => |k| { const gop = try map.getOrPut(allocator, k); - if (token == .allocated_string) { - // Free the key before recursing in case we're using an allocator - // that optimizes freeing the last allocated object. - allocator.free(k); - } if (gop.found_existing) { switch (options.duplicate_field_behavior) { .use_first => { diff --git a/lib/std/json/hashmap_test.zig b/lib/std/json/hashmap_test.zig index 674079025c..49d8caffae 100644 --- a/lib/std/json/hashmap_test.zig +++ b/lib/std/json/hashmap_test.zig @@ -5,10 +5,13 @@ const ArrayHashMap = @import("hashmap.zig").ArrayHashMap; const parseFromSlice = @import("static.zig").parseFromSlice; const parseFromSliceLeaky = @import("static.zig").parseFromSliceLeaky; +const parseFromTokenSource = @import("static.zig").parseFromTokenSource; const parseFromValue = @import("static.zig").parseFromValue; const stringifyAlloc = @import("stringify.zig").stringifyAlloc; const Value = @import("dynamic.zig").Value; +const jsonReader = @import("./scanner.zig").reader; + const T = struct { i: i32, s: []const u8, @@ -29,6 +32,31 @@ test "parse json hashmap" { try testing.expectEqual(@as(i32, 1), parsed.value.map.get("xyz").?.i); } +test "parse json hashmap while streaming" { + const doc = + \\{ + \\ "abc": {"i": 0, "s": "d"}, + \\ "xyz": {"i": 1, "s": "w"} + \\} + ; + var stream = std.io.fixedBufferStream(doc); + var json_reader = jsonReader(testing.allocator, stream.reader()); + + var parsed = try parseFromTokenSource( + ArrayHashMap(T), + testing.allocator, + &json_reader, + .{}, + ); + defer parsed.deinit(); + // Deinit our reader to invalidate its buffer + json_reader.deinit(); + + try testing.expectEqual(@as(usize, 2), parsed.value.map.count()); + try testing.expectEqualStrings("d", parsed.value.map.get("abc").?.s); + try testing.expectEqual(@as(i32, 1), parsed.value.map.get("xyz").?.i); +} + test "parse json hashmap duplicate fields" { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit();