Swift 4:JSONDecoder 在一种特定情况下失败-“操作无法完成”[关闭]

Posted

技术标签:

【中文标题】Swift 4:JSONDecoder 在一种特定情况下失败-“操作无法完成”[关闭]【英文标题】:Swift 4: JSONDecoder fails in one specific case - "The operation could not be completed" [closed] 【发布时间】:2018-04-24 15:53:07 【问题描述】:

我正在接收 JSON 文本,将其转换为数据,然后使用 JSONDecoder 创建由 JSON 文本/字符串表示的具体类型。

它确实适用于我的“复杂”数据结构(实现 Codable),甚至是一个简单的 Int 数组,如下所示:

import Foundation

let jsonTextContainigArrayOfInt: String = "[1,2,3]"
let data = jsonTextContainigArrayOfInt.data(using: .utf8)!

do 
    let arrayOfInt: [Int] = try JSONDecoder().decode([Int].self, from: data)
    for n in arrayOfInt 
        print(n)
    

catch 
    print(error)

前面的代码可以正常工作并正确创建 Int 数组并打印它们。

使用 JSON 文本中的单个 Int 执行相同方法时会出现问题:

import Foundation

let jsonTextContainigOneInt: String = "1"
let data = jsonTextContainigOneInt.data(using: .utf8)!

do 
    let myInt: Int = try JSONDecoder().decode(Int.self, from: data)
    print(myInt)

catch 
    print(error)

对于第二种方法,我收到以下错误:

“操作无法完成”

*** 编辑 ***

已存在此问题的错误报告:https://bugs.swift.org/browse/SR-6163

【问题讨论】:

"1" 不是有效的 JSON。 感谢您的时间 picciano。您能否对此发表评论:***.com/a/7487892/8284660。它指出诸如单个字符串之类的值现在应该是有效的(在 RFC 7159 中) 由于 (NS)JSONSerialization 不接受它,所以 JSONDecoder 一点也不奇怪。请参阅文档:developer.apple.com/documentation/foundation/… 此外,它似乎只符合 RFC 4627,而不是新的 (github.com/gnustep/libs-base/blob/master/Source/…) 使用JSONSerialization,查看这个答案***.com/questions/47941826/… 谢谢你们!我确实看到 JSONSerialization 不接受非数组、非字典对象作为有效的 JSON,即使(正如我告诉@picciano)在 RFC-7159 中,它现在是有效的 JSON。我现在看到 JSONDecoder 没有 JSONSerialization 中的“.allowFragments”选项。感谢@schmidt9 的澄清。 【参考方案1】:

JSONDecoder 只能将集合类型(数组或字典)解码为根对象。

在后台JSONDecoder 使用JSONSerialization 没有任何选项。但是,要解码 StringInt,您必须指定 .allowFragments 选项。

JSONSerialization.allowFragments 选项一起使用

let jsonTextContainingOneString = "1"
let data = Data(jsonTextContainingOneString.utf8)

do 
    let myString = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
    print(myString)

catch 
    print(error)

【讨论】:

【参考方案2】:

有趣...我发现了这个:

https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/JSONSerialization.swift#L120

特别是这个保护声明:

open class JSONSerialization : NSObject 
        //...

        // top level object must be an Swift.Array or Swift.Dictionary
        guard obj is [Any?] || obj is [String: Any?] else 
            return false
        

        //...
 

然后我查看了一个简单的文本字符串是否应该被视为有效的 JSON,显然现在应该被视为有效的 JSON(以前不被接受为有效的 JSON)。至少,基于这个出色的答案:https://***.com/a/7487892/8284660

这让我想知道我原来帖子上的行为是否应该是一个错误。

【讨论】:

错误报告已经存在:bugs.swift.org/browse/SR-6163

以上是关于Swift 4:JSONDecoder 在一种特定情况下失败-“操作无法完成”[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Swift 4 JSONDecoder 解码协议类型

Swift - 使用 JSONDecoder 解码 JSON 数据

使用 Swift 4 中的 JSONDecoder,缺少的键可以使用默认值而不是可选属性吗?

使用 Swift 4 中的 JSONDecoder,缺少的键可以使用默认值而不是可选属性吗?

使用 Swift 4 中的 JSONDecoder,缺少的键可以使用默认值而不是可选属性吗?

如何在 swift 4.1 和 xcode 9.3 中使用 JSONDecoder 解码嵌套的 JSON 数组和对象?