Swift 4 解码简单的根级别 JSON 值

13
根据 JSON 标准 RFC 7159,这是有效的 JSON:

RFC 7159

22

如何使用swift4的decodable将此内容解码为Int?这样做不起作用。

let twentyTwo = try? JSONDecoder().decode(Int.self, from: "22".data(using: .utf8)!)

3
这是有效的 JSON 片段,但不是有效的 JSON。 - Sulthan
1
我猜这取决于所使用的标准。在这里查看RFC 7159 https://jsonformatter.curiousconcept.com/。同时,验证其有效性的来源为https://tools.ietf.org/html/rfc7159#section-3。 - mikkelam
2
如果你将try语句放在Do..Catch中并处理错误,它会告诉你你的JSON格式不正确。那不是一个有效的JSON,你为什么还要坚持使用它呢? - Desdenova
2
JSONSerialization有一个allowFragments读取选项,但新的JSONDecoder没有这样的选项。 - Martin R
2
@Desdenova 我并不是在坚持,根据RFC 7159标准是有效的,而这个标准确实被广泛使用。如果你所说的是正确的,我猜这意味着Swift并没有使用它。 - mikkelam
显示剩余5条评论
2个回答

15
它可以使用传统的JSONSerialization.allowFragments读取选项。根据文档

allowFragments

指定解析器应允许不是NSArray或NSDictionary实例的顶级对象。

示例:

let json = "22".data(using: .utf8)!

if let value = (try? JSONSerialization.jsonObject(with: json, options: .allowFragments)) as? Int {
    print(value) // 22
}

然而,JSONDecoder没有这样的选项,并且不接受不是数组或字典的顶级对象。可以在源代码中看到,decode()方法调用JSONSerialization.jsonObject()而没有任何选项:
open func decode<T : Decodable>(_ type: T.Type, from data: Data) throws -> T {
    let topLevel: Any
    do {
       topLevel = try JSONSerialization.jsonObject(with: data)
    } catch {
        throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: error))
    }

    // ...

    return value
}

2
您可以尝试在苹果官网上提交错误报告。 - Martin R
1
我忘记写了,但我在这里提交了一个问题 https://bugs.swift.org/browse/SR-6163 - mikkelam

5
在iOS 13.1及以上版本和macOS 10.15.1及以上版本中,JSONDecoder可以处理根级别的基本类型
请查看链接文章中Martin答案下面的最新评论(截至2019年10月)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接