Logo

TrailerJson

一个轻量级的 Swift JSON 解码器,没有任何依赖。它大致基于 Swift.org 的开源版本,用于替代 Apple 的 JSONSerialisation 框架。

目前用于

详细文档 可以在这里找到

解析器

此软件包中有两个解析器

与 JSONSerialisation 相比(在优化运行时)

TrailerJson 解析器的性能几乎相当 *但是!* 结果都是原生 Swift 类型,因此使用这些结果不会产生桥接或复制成本,这是一个主要的性能优势。

TypedJson 解析器速度更快,如果您仅访问 JSON 数据的一个子集,则是理想的选择。它还可以在需要时并行化线程中的后续解析。

与 Swift.org 的版本相比

因为它在很大程度上牺牲了功能来换取只解码的性能,并且因为它返回原生 Swift 类型而无需将它们桥接到 ObjC 以实现兼容性,因此它在定义上比 Swift.org 版本更快。

概括来说

👍 非常适合解析稳定的、已知的服务 API 响应,如 GraphQL,或在嵌入式设备上使用。自包含,没有设置开销。

👎 不擅长解析/验证可能损坏的 JSON,API 可能会突然包含意外的 schema 条目,或者当 Decodable 类型更好地为您服务时。

示例

let url = URL(string: "http://date.jsontest.com")!
let data = try await URLSession.shared.data(from: url).0
// TrailerJson - parse in one go to [String: Sendable]
if let json = try data.asJsonObject(),      // parse as dictionary
   let timeField = json["time"],
   let timeString = timeField as? String {
   
    print("The time is", timeString)
}
// TypedJson - scan the data and only parse 'time' as a String
if let json = try data.asTypedJson(),         // scan data
   let timeField = try? json["time"],
   let timeString = try? timeField.asString { // parse field
   
    print("The time is", timeString)
}

TrailerJson 直接使用原始字节,因此它可以接受来自任何暴露原始字节缓冲区类型的数据,例如 NIO 的 ByteBuffer,而无需昂贵的类型转换或中间复制。

let byteBuffer: ByteBuffer = ...
// TrailerJson
let jsonArray = try byteBuffer.withVeryUnsafeBytes { 
    try TrailerJson.parse(bytes: $0) as? [Sendable]
}
let number = jsonArray[1] as? Int
print(number)
// TypedJson
let jsonArray = try byteBuffer.withVeryUnsafeBytes { 
    try TypedJson.parse(bytes: $0)
}
let number = try jsonArray[1].asInt
print(number)
// TypedJson - using bytesNoCopy, lazy parsing (max performance, but with caveats!)
let number = try byteBuffer.withVeryUnsafeBytes { 

    // jsonArray and any Entry from it must not be accessed outside the closure 
    let jsonArray = try TypedJson.parse(bytesNoCopy: $0)

    // `secondEntry` reads from the original bytes, so it can't escape 
    let secondEntry = try jsonArray[1]

    // but parsed values can escape
    return try secondEntry.asInt
}
print(number)        

如果您需要将 TypedJson 条目传递给需要非类型化字典的方法,您可以使用 parse 方法来急切地解析一个块 - 但请注意,对于大型数据集来说,这可能会很慢,因此最好用于非常特定的情况!

// TypedJson - eager parsing (slowest performance)
let numberArray = try byteBuffer.withVeryUnsafeBytes { 

    // numbers and any Entry from it must not be accessed outside the closure 
    let numbers = try TypedJson.parse(bytes: $0)

    // but parsed value can escape - note that parsing the whole document would be 
    // very slow, so for cases like these the `TrailerJson` parser is 10x faster!
    return try numbers.parsed as! [Int]
}
let number = numberArray[1]
print(number)        

注意

许可证

版权所有 (c) 2023-2024 Paul Tsochantaris. 根据 Apache License v2.0,带有运行时库例外,按照 其基于的开源材料