json: respect duplicate_field_behavior in std.json.Value.jsonParse

This commit is contained in:
Techatrix 2024-06-26 23:37:11 +02:00 committed by Andrew Kelley
parent fe66a12a23
commit 8f7b50e2c4
3 changed files with 44 additions and 2 deletions

View File

@ -147,7 +147,19 @@ fn handleCompleteValue(stack: *Array, allocator: Allocator, source: anytype, val
// stack: [..., .object]
var object = &stack.items[stack.items.len - 1].object;
try object.put(key, value);
const gop = try object.getOrPut(key);
if (gop.found_existing) {
switch (options.duplicate_field_behavior) {
.use_first => {},
.@"error" => return error.DuplicateField,
.use_last => {
gop.value_ptr.* = value;
},
}
} else {
gop.value_ptr.* = value;
}
// This is an invalid state to leave the stack in,
// so we have to process the next token before we return.

View File

@ -181,6 +181,34 @@ test "escaped characters" {
try testing.expectEqualSlices(u8, obj.get("surrogatepair").?.string, "😂");
}
test "Value with duplicate fields" {
var arena_allocator = std.heap.ArenaAllocator.init(std.testing.allocator);
defer arena_allocator.deinit();
const doc =
\\{
\\ "abc": 0,
\\ "abc": 1
\\}
;
try testing.expectError(error.DuplicateField, parseFromSliceLeaky(std.json.Value, arena_allocator.allocator(), doc, .{
.duplicate_field_behavior = .@"error",
}));
const first = try parseFromSliceLeaky(std.json.Value, arena_allocator.allocator(), doc, .{
.duplicate_field_behavior = .use_first,
});
try testing.expectEqual(@as(usize, 1), first.object.count());
try testing.expectEqual(@as(i64, 0), first.object.get("abc").?.integer);
const last = try parseFromSliceLeaky(std.json.Value, arena_allocator.allocator(), doc, .{
.duplicate_field_behavior = .use_last,
});
try testing.expectEqual(@as(usize, 1), last.object.count());
try testing.expectEqual(@as(i64, 1), last.object.get("abc").?.integer);
}
test "Value.jsonStringify" {
var vals = [_]Value{
.{ .integer = 1 },

View File

@ -28,7 +28,9 @@ fn testLowLevelScanner(s: []const u8) !void {
}
}
fn testHighLevelDynamicParser(s: []const u8) !void {
var parsed = try parseFromSlice(Value, testing.allocator, s, .{});
var parsed = try parseFromSlice(Value, testing.allocator, s, .{
.duplicate_field_behavior = .use_first,
});
defer parsed.deinit();
}