Swift 4:JSONDecoder在一种特定情况下失败-“操作无法完成”
我接收JSON文本,将其转换为数据,然后使用JSONDecoder创建一个具体类型,由JSON文本/字符串表示 它确实适用于我的复杂数据结构,它实现了Codable,甚至是一个简单的Int数组,如下所示:Swift 4:JSONDecoder在一种特定情况下失败-“操作无法完成”,json,swift,decode,codable,jsondecoder,Json,Swift,Decode,Codable,Jsondecoder,我接收JSON文本,将其转换为数据,然后使用JSONDecoder创建一个具体类型,由JSON文本/字符串表示 它确实适用于我的复杂数据结构,它实现了Codable,甚至是一个简单的Int数组,如下所示: import Foundation let jsonTextContainigArrayOfInt: String = "[1,2,3]" let data = jsonTextContainigArrayOfInt.data(using: .utf8)! do { let arr
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)
}
对于第二种方法,我得到以下错误:
操作无法完成
***编辑***
此错误报告已存在:有趣。。。我发现: 特别是这一声明:
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。至少,基于这个极好的答案:
这让我想知道我的原始帖子上的行为是否应该是一个bug。JSONDecoder只能将集合类型数组或字典解码为根对象
幕后的JSONDecoder使用JSONSerialization,没有任何选项。但是,要解码字符串或Int,必须指定.allowFragments选项
将JSONSerialization与.allowFragments选项一起使用
1不是有效的JSON。感谢您的时间picciano。你能对此发表评论吗:。它指出,像单个字符串这样的值现在在RFC 7159中应该是有效的,因为NSJSONSerialization不接受它,所以JSONDecoder也不会感到惊讶。请参阅文档:另外,似乎它的RFC4627仅兼容,而不是新版本使用JSONSerialization,请检查此答案谢谢!我确实看到JSONSerialization不接受非数组、非字典对象作为有效的JSON,尽管我在RFC-7159中告诉@picciano,它现在是有效的JSON。我现在看到,JSONDecoder没有JSONSerialization中的.allowFragments选项。感谢您的澄清@schmidt9.Bug报告已经存在:
let jsonTextContainingOneString = "1"
let data = Data(jsonTextContainingOneString.utf8)
do {
let myString = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
print(myString)
}
catch {
print(error)
}