解析Swift 4中包含字符串和int的JSON数组
我有一个简单的数组解析Swift 4中包含字符串和int的JSON数组,json,swift,Json,Swift,我有一个简单的数组 Array[4][ "A", 1, "A1", 13 ] 但是,当JSON数组同时包含int和string时,如何解析它呢?如果还没有,我可以将里面的所有值转换成字符串,但是我找不到任何函数来实现这一点 谢谢 使用可编码的复杂方式 使用unkeyedContainer对数组进行解码 使用循环,同时使用条件!在一个do-catch块中对Int进行搜索和解码。如果解码字符串失败 使用传统的json串行化的简便方法 将对象反序列化为[CustomStringCo
Array[4][
"A",
1,
"A1",
13
]
但是,当JSON数组同时包含int和string时,如何解析它呢?如果还没有,我可以将里面的所有值转换成字符串,但是我找不到任何函数来实现这一点
谢谢
可编码的复杂方式
- 使用
unkeyedContainer对数组进行解码
- 使用
循环,同时使用条件!在一个do-catch
块中对Int
进行搜索和解码。如果解码字符串失败
json串行化的简便方法
- 将对象反序列化为
[CustomStringConvertible]
,并使用“\($0)”将数组映射到[String]
let jsonData = """
["A", 1, "A1", 13, 15, 2, "B"]
""".data(using: .utf8)!
do {
let decodedArray = try JSONDecoder().decode([StringOrIntType].self, from:jsonData)
// Here, you have your Array
print(decodedArray) // [.string("A"), .int(1), .string("A1"), .int(13), .int(15), .int(2), .string("B")]
// If you want to get elements from this Array, you might do something like below
decodedArray.forEach({ (value) in
if case .string(let integer) = value {
print(integer) // "A", "A1", "B"
}
if case .int(let int) = value {
print(int) // 1, 13, 15, 2
}
})
} catch {
print(error)
}
这是一个示例,如果项目是成对的且类型顺序相同,则如何使用Decodable
解码数组:
let jsonArray = """
["A", 1, "A1", 13]
"""
struct Item : Decodable {
var array = [String]()
init(from decoder: Decoder) throws {
var arrayContainer = try decoder.unkeyedContainer()
while !arrayContainer.isAtEnd {
let string = try arrayContainer.decode(String.self)
let int = try arrayContainer.decode(Int.self)
array.append(String(int))
array.append(string)
}
}
}
let data = Data(jsonArray.utf8)
do {
let result = try JSONDecoder().decode(Item.self, from: data)
print(result.array)
} catch { print(error) }
可编码的复杂方式
- 使用
unkeyedContainer对数组进行解码
- 使用
循环,同时使用条件!在一个do-catch
块中对Int
进行搜索和解码。如果解码字符串失败
json串行化的简便方法
- 将对象反序列化为
[CustomStringConvertible]
,并使用“\($0)”将数组映射到[String]
let jsonData = """
["A", 1, "A1", 13, 15, 2, "B"]
""".data(using: .utf8)!
do {
let decodedArray = try JSONDecoder().decode([StringOrIntType].self, from:jsonData)
// Here, you have your Array
print(decodedArray) // [.string("A"), .int(1), .string("A1"), .int(13), .int(15), .int(2), .string("B")]
// If you want to get elements from this Array, you might do something like below
decodedArray.forEach({ (value) in
if case .string(let integer) = value {
print(integer) // "A", "A1", "B"
}
if case .int(let int) = value {
print(int) // 1, 13, 15, 2
}
})
} catch {
print(error)
}
这是一个示例,如果项目是成对的且类型顺序相同,则如何使用Decodable
解码数组:
let jsonArray = """
["A", 1, "A1", 13]
"""
struct Item : Decodable {
var array = [String]()
init(from decoder: Decoder) throws {
var arrayContainer = try decoder.unkeyedContainer()
while !arrayContainer.isAtEnd {
let string = try arrayContainer.decode(String.self)
let int = try arrayContainer.decode(Int.self)
array.append(String(int))
array.append(string)
}
}
}
let data = Data(jsonArray.utf8)
do {
let result = try JSONDecoder().decode(Item.self, from: data)
print(result.array)
} catch { print(error) }
将JSON示例
[1,“1”]
粘贴到中可以实现以下Codable
实现:
typealias IntOrStrings = [IntOrString]
enum IntOrString: Codable {
case integer(Int)
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Int.self) {
self = .integer(x)
return
}
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
throw DecodingError.typeMismatch(IntOrString.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for IntOrString"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .integer(let x):
try container.encode(x)
case .string(let x):
try container.encode(x)
}
}
}
这允许您执行以下操作:
let items = try IntStrings("[1, \"1\"]")
// Now you have:
// items == [.integer(1), .string("1")]
// so you can map or iterate over this
这是从JSON中表示整型或字符串数组的最安全的方式。将JSON示例
[1,“1”]
粘贴到中可以实现以下可编码的实现:
typealias IntOrStrings = [IntOrString]
enum IntOrString: Codable {
case integer(Int)
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Int.self) {
self = .integer(x)
return
}
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
throw DecodingError.typeMismatch(IntOrString.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for IntOrString"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .integer(let x):
try container.encode(x)
case .string(let x):
try container.encode(x)
}
}
}
这允许您执行以下操作:
let items = try IntStrings("[1, \"1\"]")
// Now you have:
// items == [.integer(1), .string("1")]
// so you can map or iterate over this
这是从JSON中表示整型或字符串数组的最安全的方式。您将得到数组
元素,如字符串
或整型
,类似于枚举
类型的数组。因此,您可以在枚举的帮助下解析底层类型
将基础类型结构化为:
enum StringOrIntType: Codable {
case string(String)
case int(Int)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
do {
self = try .string(container.decode(String.self))
} catch DecodingError.typeMismatch {
do {
self = try .int(container.decode(Int.self))
} catch DecodingError.typeMismatch {
throw DecodingError.typeMismatch(StringOrIntType.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Encoded payload not of an expected type"))
}
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .int(let int):
try container.encode(int)
case .string(let string):
try container.encode(string)
}
}
}
解码过程:
let jsonData = """
["A", 1, "A1", 13, 15, 2, "B"]
""".data(using: .utf8)!
do {
let decodedArray = try JSONDecoder().decode([StringOrIntType].self, from:jsonData)
// Here, you have your Array
print(decodedArray) // [.string("A"), .int(1), .string("A1"), .int(13), .int(15), .int(2), .string("B")]
// If you want to get elements from this Array, you might do something like below
decodedArray.forEach({ (value) in
if case .string(let integer) = value {
print(integer) // "A", "A1", "B"
}
if case .int(let int) = value {
print(int) // 1, 13, 15, 2
}
})
} catch {
print(error)
}
从对已接受答案的评论来看:您不必再担心物品的顺序。
您将获得元素的Array
作为String
或Int
,这类似于enum
类型的数组。因此,您可以在枚举的帮助下解析底层类型
将基础类型结构化为:
enum StringOrIntType: Codable {
case string(String)
case int(Int)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
do {
self = try .string(container.decode(String.self))
} catch DecodingError.typeMismatch {
do {
self = try .int(container.decode(Int.self))
} catch DecodingError.typeMismatch {
throw DecodingError.typeMismatch(StringOrIntType.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Encoded payload not of an expected type"))
}
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .int(let int):
try container.encode(int)
case .string(let string):
try container.encode(string)
}
}
}
解码过程:
let jsonData = """
["A", 1, "A1", 13, 15, 2, "B"]
""".data(using: .utf8)!
do {
let decodedArray = try JSONDecoder().decode([StringOrIntType].self, from:jsonData)
// Here, you have your Array
print(decodedArray) // [.string("A"), .int(1), .string("A1"), .int(13), .int(15), .int(2), .string("B")]
// If you want to get elements from this Array, you might do something like below
decodedArray.forEach({ (value) in
if case .string(let integer) = value {
print(integer) // "A", "A1", "B"
}
if case .int(let int) = value {
print(int) // 1, 13, 15, 2
}
})
} catch {
print(error)
}
从对已接受答案的评论来看:您不必再担心物品的顺序。
哦,我想为我的整个应用程序保持可编码,但是这个JSON非常复杂(这个数组只是整个应用程序的一部分)。我想我会坚持使用JSONSerialization来完成这一步。谢谢,瓦迪安!如果项目是成对的,并且顺序String
,Int
,String
,Int
是有保证的,那么Codable
就不那么复杂,可能更有效。在的每次迭代中,当循环解码对时,顺序总是相同的。你能举个简单的例子吗?谢谢很好的解决方案!非常感谢瓦迪安。您帮了我很多。@vadian,实际上,通过使用关联枚举
类型,可以在这里放弃排序。Codable
不再复杂,而且init(from:)
更干净。检查我的答案。哦,我想为我的整个应用程序保持可编码,但是这个JSON非常复杂(这个数组只是整个应用程序的一部分)。我想我会坚持使用JSONSerialization来完成这一步。谢谢,瓦迪安!如果项目是成对的,并且顺序String
,Int
,String
,Int
是有保证的,那么Codable
就不那么复杂,可能更有效。在的每次迭代中,当循环解码对时,顺序总是相同的。你能举个简单的例子吗?谢谢很好的解决方案!非常感谢瓦迪安。您帮了我很多。@vadian,实际上,通过使用关联枚举
类型,可以在这里放弃排序。Codable
不再复杂,而且init(from:)
更干净。检查我的答案。另一方面,对错误处理要更加明确。您可以省略init(from:)
中的条件绑定。请参阅我的答案。另一方面,请更明确地说明错误处理。您可以省略init(from:)
中的条件绑定。看看我的答案。哇,这是一个很好的解决方案!谢谢你,内姆。这太简单了,我打算改用你的。哇,这是一个很好的解决方案!谢谢你,内姆。这太简单了,我打算改用你的。