mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
Merge pull request #16707 from marler8997/jsonStringifyBigNumbers
std.json: fix roundtrip stringify for large integers
This commit is contained in:
commit
36c57c3ba1
@ -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_nonportable_numbers_as_strings: 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.
|
||||
/// * When option `emit_nonportable_numbers_as_strings` is true, 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".
|
||||
@ -399,21 +402,15 @@ pub fn WriteStream(
|
||||
pub fn write(self: *Self, value: anytype) Error!void {
|
||||
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;
|
||||
}
|
||||
.Int => {
|
||||
try self.valueStart();
|
||||
try self.stream.print("\"{}\"", .{value});
|
||||
if (self.options.emit_nonportable_numbers_as_strings and
|
||||
(value <= -(1 << 53) or value >= (1 << 53)))
|
||||
{
|
||||
try self.stream.print("\"{}\"", .{value});
|
||||
} else {
|
||||
try self.stream.print("{}", .{value});
|
||||
}
|
||||
self.valueDone();
|
||||
return;
|
||||
},
|
||||
|
||||
@ -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 "nonportable numbers" {
|
||||
try testStringify("9999999999999999", 9999999999999999, .{});
|
||||
try testStringify("\"9999999999999999\"", 9999999999999999, .{ .emit_nonportable_numbers_as_strings = true });
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user