diff --git a/lib/std/json.zig b/lib/std/json.zig index 9f678fb4aa..baf93af47c 100644 --- a/lib/std/json.zig +++ b/lib/std/json.zig @@ -1422,23 +1422,37 @@ fn parseInternal( }; }, .Float, .ComptimeFloat => { - const numberToken = switch (token) { - .Number => |n| n, + switch (token) { + .Number => |numberToken| return try std.fmt.parseFloat(T, numberToken.slice(tokens.slice, tokens.i - 1)), + .String => |stringToken| return try std.fmt.parseFloat(T, stringToken.slice(tokens.slice, tokens.i - 1)), else => return error.UnexpectedToken, - }; - return try std.fmt.parseFloat(T, numberToken.slice(tokens.slice, tokens.i - 1)); + } }, .Int, .ComptimeInt => { - const numberToken = switch (token) { - .Number => |n| n, + switch (token) { + .Number => |numberToken| { + if (numberToken.is_integer) + return try std.fmt.parseInt(T, numberToken.slice(tokens.slice, tokens.i - 1), 10); + const float = try std.fmt.parseFloat(f128, numberToken.slice(tokens.slice, tokens.i - 1)); + if (@round(float) != float) return error.InvalidNumber; + if (float > std.math.maxInt(T) or float < std.math.minInt(T)) return error.Overflow; + return @floatToInt(T, float); + }, + .String => |stringToken| { + return std.fmt.parseInt(T, stringToken.slice(tokens.slice, tokens.i - 1), 10) catch |err| { + switch (err) { + error.Overflow => return err, + error.InvalidCharacter => { + const float = try std.fmt.parseFloat(f128, stringToken.slice(tokens.slice, tokens.i - 1)); + if (@round(float) != float) return error.InvalidNumber; + if (float > std.math.maxInt(T) or float < std.math.minInt(T)) return error.Overflow; + return @floatToInt(T, float); + }, + } + }; + }, else => return error.UnexpectedToken, - }; - if (numberToken.is_integer) - return try std.fmt.parseInt(T, numberToken.slice(tokens.slice, tokens.i - 1), 10); - const float = try std.fmt.parseFloat(f128, numberToken.slice(tokens.slice, tokens.i - 1)); - if (@round(float) != float) return error.InvalidNumber; - if (float > std.math.maxInt(T) or float < std.math.minInt(T)) return error.Overflow; - return @floatToInt(T, float); + } }, .Optional => |optionalInfo| { if (token == .Null) { diff --git a/lib/std/json/test.zig b/lib/std/json/test.zig index df0403cf5f..2a590fdf15 100644 --- a/lib/std/json/test.zig +++ b/lib/std/json/test.zig @@ -2046,6 +2046,11 @@ test "parse" { try testing.expectEqual(@as([3]u8, "foo".*), try parse([3]u8, &ts, ParseOptions{})); ts = TokenStream.init("[]"); try testing.expectEqual(@as([0]u8, undefined), try parse([0]u8, &ts, ParseOptions{})); + + ts = TokenStream.init("\"12345678901234567890\""); + try testing.expectEqual(@as(u64, 12345678901234567890), try parse(u64, &ts, ParseOptions{})); + ts = TokenStream.init("\"123.456\""); + try testing.expectEqual(@as(f64, 123.456), try parse(f64, &ts, ParseOptions{})); } test "parse into enum" {