Swift 的 JSONSafeEncoding

这个库是 JSONEncoder 及其相关类型的直接副本。它扩展了 JSONEncoder 的 nonConformingFloatEncodingStrategy,为开发者提供更多处理 NaN / Infinity / -Infinity 值的选项。

为什么?

当使用 Codable 时,为了 JSON 编码的目的,确保所有浮点数值不包含 NaN 或 Infinity 是一个繁琐的任务。可行的选择是自定义数字类型(方法过于笨重),或者修改编码过程。

由于 一些 选项已经存在,似乎这是最谨慎且侵入性最小的选择。

有哪些选项?

现在 nonConformingFloatEncodingStrategy 选项包含以下值:

.zero

当遇到 NaN/Infinity 时,输出 0 作为值。这是默认选项。这是与 JSONDecoder 结合使用的最安全选项,因为结构体中要赋值的值无需以任何方式更改。

.null

当遇到 NaN/Infinity 时,输出 null。这模仿了 Javascript 处理这些值的方式。

.convertToString(...)

将 NaN/Infinity 转换为字符串。这个选项已经存在,但没有默认值或指南。

.throw

这是原始行为,当遇到 NaN/Infinity 时会抛出错误。

.convertToStringDefaults

这与 .convertToString(...) 类似,但它提供了与 Python 等语言匹配的默认值。默认值是 NaNInfinity-Infinity

示例

struct TestStruct: Codable {
    let myString: String
    let myDouble: Double
}

let test = TestStruct(myString: "this is a test", myDouble: Double.nan)

let encoder = JSONSafeEncoder()
encoder.nonConformingFloatEncodingStrategy = .zero
encoder.outputFormatting = .prettyPrinted

let json = try encoder.encode(test)
XCTAssertNotNil(json)

let prettyString = String(data: json, encoding: .utf8)!
print(prettyString)


let decoder = JSONDecoder()
let newTest = try decoder.decode(TestStruct.self, from: json)

XCTAssertEqual(newTest.myString, "this is a test")
XCTAssertEqual(newTest.myDouble, 0)

许可证

Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See https://swiftlang.cn/LICENSE.txt for license information
See https://swiftlang.cn/CONTRIBUTORS.txt for the list of Swift project authors

TWILIO NOTICE: Filenames and functionality have been modified from their original counterparts @
https://github.com/apple/swift-corelibs-foundation/blob/main/Sources/Foundation/JSONEncoder.swift

Copyright (c) 2023 Twilio Inc.