diff --git a/lib/std/json/stringify.zig b/lib/std/json/stringify.zig index 3e00531eaa..aa719e620b 100644 --- a/lib/std/json/stringify.zig +++ b/lib/std/json/stringify.zig @@ -33,6 +33,9 @@ pub const StringifyOptions = struct { /// Should unicode characters be escaped in strings? escape_unicode: bool = false, + + /// When true, renders numbers outside the range `±1<<53` (the precise integer range of f64) as JSON strings in base 10. + emit_big_numbers_quoted: bool = false, }; /// Writes the given value to the `std.io.Writer` stream. @@ -161,7 +164,7 @@ pub fn writeStreamArbitraryDepth( /// * Zig `bool` -> JSON `true` or `false`. /// * Zig `?T` -> `null` or the rendering of `T`. /// * Zig `i32`, `u64`, etc. -> JSON number or string. -/// * If the value is outside the range `±1<<53` (the precise integer rage of f64), it is rendered as a JSON string in base 10. Otherwise, it is rendered as JSON number. +/// * If the value is outside the range `±1<<53` (the precise integer range of f64), it is rendered as a JSON string in base 10. Otherwise, it is rendered as JSON number. /// * Zig floats -> JSON number or string. /// * If the value cannot be precisely represented by an f64, it is rendered as a JSON string. Otherwise, it is rendered as JSON number. /// * TODO: Float rendering will likely change in the future, e.g. to remove the unnecessary "e+00". @@ -400,20 +403,16 @@ pub fn WriteStream( const T = @TypeOf(value); switch (@typeInfo(T)) { .Int => |info| { - if (info.bits < 53) { - try self.valueStart(); - try self.stream.print("{}", .{value}); - self.valueDone(); - return; - } - if (value < 4503599627370496 and (info.signedness == .unsigned or value > -4503599627370496)) { - try self.valueStart(); - try self.stream.print("{}", .{value}); - self.valueDone(); - return; - } + const emit_unquoted = + if (!self.options.emit_big_numbers_quoted) true + else if (info.bits < 53) true + else (value < 4503599627370496 and (info.signedness == .unsigned or value > -4503599627370496)); try self.valueStart(); - try self.stream.print("\"{}\"", .{value}); + if (emit_unquoted) { + try self.stream.print("{}", .{value}); + } else { + try self.stream.print("\"{}\"", .{value}); + } self.valueDone(); return; }, diff --git a/lib/std/json/stringify_test.zig b/lib/std/json/stringify_test.zig index 4eec97e667..c2c6b6f5e7 100644 --- a/lib/std/json/stringify_test.zig +++ b/lib/std/json/stringify_test.zig @@ -126,6 +126,7 @@ test "stringify basic types" { try testStringify("4.2e+01", 42.0, .{}); try testStringify("42", @as(u8, 42), .{}); try testStringify("42", @as(u128, 42), .{}); + try testStringify("9999999999999999", 9999999999999999, .{}); try testStringify("4.2e+01", @as(f32, 42), .{}); try testStringify("4.2e+01", @as(f64, 42), .{}); try testStringify("\"ItBroke\"", @as(anyerror, error.ItBroke), .{}); @@ -432,3 +433,8 @@ test "print" { ; try std.testing.expectEqualStrings(expected, result); } + +test "big integers" { + try testStringify("9999999999999999", 9999999999999999, .{}); + try testStringify("\"9999999999999999\"", 9999999999999999, .{ .emit_big_numbers_quoted = true }); +}