diff --git a/lib/std/json/dynamic.zig b/lib/std/json/dynamic.zig index 5e99b52d44..81ca1db2da 100644 --- a/lib/std/json/dynamic.zig +++ b/lib/std/json/dynamic.zig @@ -93,11 +93,11 @@ pub const Value = union(enum) { stack.items[stack.items.len - 1] == .array or (stack.items[stack.items.len - 2] == .object and stack.items[stack.items.len - 1] == .string)); - switch (try source.nextAlloc(allocator, .alloc_if_needed)) { - inline .string, .allocated_string => |s| { + switch (try source.nextAlloc(allocator, .alloc_always)) { + .allocated_string => |s| { return try handleCompleteValue(&stack, allocator, source, Value{ .string = s }) orelse continue; }, - inline .number, .allocated_number => |slice| { + .allocated_number => |slice| { return try handleCompleteValue(&stack, allocator, source, Value.parseFromNumberSlice(slice)) orelse continue; }, @@ -106,9 +106,9 @@ pub const Value = union(enum) { .false => return try handleCompleteValue(&stack, allocator, source, Value{ .bool = false }) orelse continue, .object_begin => { - switch (try source.nextAlloc(allocator, .alloc_if_needed)) { + switch (try source.nextAlloc(allocator, .alloc_always)) { .object_end => return try handleCompleteValue(&stack, allocator, source, Value{ .object = ObjectMap.init(allocator) }) orelse continue, - inline .string, .allocated_string => |key| { + .allocated_string => |key| { try stack.appendSlice(&[_]Value{ Value{ .object = ObjectMap.init(allocator) }, Value{ .string = key }, @@ -152,7 +152,7 @@ fn handleCompleteValue(stack: *Array, allocator: Allocator, source: anytype, val // This is an invalid state to leave the stack in, // so we have to process the next token before we return. - switch (try source.nextAlloc(allocator, .alloc_if_needed)) { + switch (try source.nextAlloc(allocator, .alloc_always)) { .object_end => { // This object is complete. value = stack.pop(); @@ -160,7 +160,7 @@ fn handleCompleteValue(stack: *Array, allocator: Allocator, source: anytype, val if (stack.items.len == 0) return value; continue; }, - inline .string, .allocated_string => |next_key| { + .allocated_string => |next_key| { // We've got another key. try stack.append(Value{ .string = next_key }); // stack: [..., .object, .string] diff --git a/lib/std/json/dynamic_test.zig b/lib/std/json/dynamic_test.zig index 220c94edcf..144f108cb6 100644 --- a/lib/std/json/dynamic_test.zig +++ b/lib/std/json/dynamic_test.zig @@ -15,6 +15,7 @@ const parseFromValueLeaky = @import("static.zig").parseFromValueLeaky; const ParseOptions = @import("static.zig").ParseOptions; const jsonReader = @import("scanner.zig").reader; +const JsonReader = @import("scanner.zig").Reader; test "json.parser.dynamic" { const s = @@ -288,3 +289,42 @@ test "polymorphic parsing" { try testing.expect(tree.div.color == .blue); try testing.expectEqualStrings("Cancel", tree.div.children[1].button.caption); } + +test "long object value" { + const value = "01234567890123456789"; + const doc = "{\"key\":\"" ++ value ++ "\"}"; + var fbs = std.io.fixedBufferStream(doc); + var reader = smallBufferJsonReader(testing.allocator, fbs.reader()); + defer reader.deinit(); + var parsed = try parseFromTokenSource(Value, testing.allocator, &reader, .{}); + defer parsed.deinit(); + + try testing.expectEqualStrings(value, parsed.value.object.get("key").?.string); +} + +test "many object keys" { + const doc = + \\{ + \\ "k1": "v1", + \\ "k2": "v2", + \\ "k3": "v3", + \\ "k4": "v4", + \\ "k5": "v5" + \\} + ; + var fbs = std.io.fixedBufferStream(doc); + var reader = smallBufferJsonReader(testing.allocator, fbs.reader()); + defer reader.deinit(); + var parsed = try parseFromTokenSource(Value, testing.allocator, &reader, .{}); + defer parsed.deinit(); + + try testing.expectEqualStrings("v1", parsed.value.object.get("k1").?.string); + try testing.expectEqualStrings("v2", parsed.value.object.get("k2").?.string); + try testing.expectEqualStrings("v3", parsed.value.object.get("k3").?.string); + try testing.expectEqualStrings("v4", parsed.value.object.get("k4").?.string); + try testing.expectEqualStrings("v5", parsed.value.object.get("k5").?.string); +} + +fn smallBufferJsonReader(allocator: Allocator, io_reader: anytype) JsonReader(16, @TypeOf(io_reader)) { + return JsonReader(16, @TypeOf(io_reader)).init(allocator, io_reader); +}