如何在 Swift 中解码 JSON 中的大数
How to decode a large number from JSON in Swift
如何像这样解析 JSON:
let json = "{\"key\":18446744073709551616}"
struct Foo: Decodable {
let key: UInt64
}
let coder = JSONDecoder()
let test = try! coder.decode(Foo.self, from: json.data(using: .utf8)!)
问题是这个数字对于 UInt64
来说太大了。我知道 Swift.
中没有更大的整数类型
Parsed JSON number <18446744073709551616> does not fit in UInt64
我不介意将其设为 String
或 Data
,但这是不允许的,因为 JSONDecoder
知道它应该是一个数字:
Expected to decode String but found a number instead.
您可以使用 Decimal
代替:
let json = "{\"key\":184467440737095516160000001}"
struct Foo: Decodable {
let key: Decimal
}
let coder = JSONDecoder()
let test = try! coder.decode(Foo.self, from: json.data(using: .utf8)!)
print(test) // Foo(key: 184467440737095516160000001)
Decimal
是 NSDecimalNumber
的 Swift 覆盖类型,
... can represent any number that can be expressed as mantissa x 10^exponent
where mantissa is a decimal integer up to 38 digits long, and exponent is an integer from –128 through 127.
如果不需要完全精度,您也可以将其解析为 Double
:
struct Foo: Decodable {
let key: Double
}
let coder = JSONDecoder()
let test = try! coder.decode(Foo.self, from: json.data(using: .utf8)!)
print(test) // Foo(key: 1.8446744073709552e+36)
似乎是JSON解码器在幕后使用NSDecimalNumber
struct Foo: Decodable {
let key: Int
}
// this is 1 + the mantissa of NSDecimalNumber.maximum
let json = "{\"key\":340282366920938463463374607431768211456}"
let coder = JSONDecoder()
let test = try! coder.decode(Foo.self, from: json.data(using: .utf8)!)
即使在 DecodingError 中,数字也没有准确表示:
Parsed JSON number <340282366920938463463374607431768211450> does not fit in Int.
因此,如果您希望能够以最大精度解码(尽管您仍然可能会默默地失去精度),请使用 Decimal
。否则你只需要对发给你的人大喊大叫 JSON.
请注意,虽然 documentation 表示
mantissa is a decimal integer up to 38 digits
它实际上是一个 128 位无符号整数,因此它也可以表示一些 39 位数字,如上所示。
如何像这样解析 JSON:
let json = "{\"key\":18446744073709551616}"
struct Foo: Decodable {
let key: UInt64
}
let coder = JSONDecoder()
let test = try! coder.decode(Foo.self, from: json.data(using: .utf8)!)
问题是这个数字对于 UInt64
来说太大了。我知道 Swift.
Parsed JSON number <18446744073709551616> does not fit in UInt64
我不介意将其设为 String
或 Data
,但这是不允许的,因为 JSONDecoder
知道它应该是一个数字:
Expected to decode String but found a number instead.
您可以使用 Decimal
代替:
let json = "{\"key\":184467440737095516160000001}"
struct Foo: Decodable {
let key: Decimal
}
let coder = JSONDecoder()
let test = try! coder.decode(Foo.self, from: json.data(using: .utf8)!)
print(test) // Foo(key: 184467440737095516160000001)
Decimal
是 NSDecimalNumber
的 Swift 覆盖类型,
... can represent any number that can be expressed as
mantissa x 10^exponent
where mantissa is a decimal integer up to 38 digits long, and exponent is an integer from –128 through 127.
如果不需要完全精度,您也可以将其解析为 Double
:
struct Foo: Decodable {
let key: Double
}
let coder = JSONDecoder()
let test = try! coder.decode(Foo.self, from: json.data(using: .utf8)!)
print(test) // Foo(key: 1.8446744073709552e+36)
似乎是JSON解码器在幕后使用NSDecimalNumber
struct Foo: Decodable {
let key: Int
}
// this is 1 + the mantissa of NSDecimalNumber.maximum
let json = "{\"key\":340282366920938463463374607431768211456}"
let coder = JSONDecoder()
let test = try! coder.decode(Foo.self, from: json.data(using: .utf8)!)
即使在 DecodingError 中,数字也没有准确表示:
Parsed JSON number <340282366920938463463374607431768211450> does not fit in Int.
因此,如果您希望能够以最大精度解码(尽管您仍然可能会默默地失去精度),请使用 Decimal
。否则你只需要对发给你的人大喊大叫 JSON.
请注意,虽然 documentation 表示
mantissa is a decimal integer up to 38 digits
它实际上是一个 128 位无符号整数,因此它也可以表示一些 39 位数字,如上所示。