我有一个命名的json对象数组,我通过API调用接收它。
{
"Images": [{
"Width": 800,
"Height": 590,
"Url": "https://obfuscated.image.url/image1.jpg"
}, {
"Width": 800,
"Height": 533,
"Url": "https://obfuscated.image.url/image2.jpg"
}, {
"Width": 800,
"Height": 478,
"Url": "https://obfuscated.image.url/image3.jpg"
}]
}
对象属于Image类型,我已经定义了它并且具有可以解码单个Image对象的解码函数。图像看起来像:
struct Image : Codable {
let width: CGFloat
let height: CGFloat
let url: String
enum ImageKey: String, CodingKey {
case width = "Width"
case height = "Height"
case url = "Url"
}
init(from decoder: Decoder) throws
{
let container = try decoder.container(keyedBy: ImageKey.self)
width = try container.decodeIfPresent(CGFloat.self, forKey: .width) ?? 0.0
height = try container.decodeIfPresent(CGFloat.self, forKey: .height) ?? 0.0
url = try container.decodeIfPresent(String.self, forKey: .url) ?? ""
}
func encode(to encoder: Encoder) throws
{
}
}
我为这个场景写了一个测试,但这是我难倒的地方!测试失败(自然),看起来像这样:
func testManyImages() throws {
if let urlManyImages = urlManyImages {
self.data = try? Data(contentsOf: urlManyImages)
}
let jsonDecoder = JSONDecoder()
if let data = self.data {
if let _images:[Image] = try? jsonDecoder.decode([Image].self, from: data) {
self.images = _images
}
}
XCTAssertNotNil(self.images)
}
我的问题是:
如何通过名称"图像"访问图像数组?或者其他?
感谢阅读,并一如既往地感谢任何帮助。
答案 0 :(得分:3)
我认为您的Codable结构是错误的。它应该是:
struct JSONStructure: Codable {
let images: [Images]
private enum CodingKeys: String, CodingKey {
case images = "Images"
}
}
struct Images: Codable {
let width: CGFloat
let height: CGFloat
let url: String
private enum CodingKeys: String, CodingKey {
case width = "Width"
case height = "Height"
case url = "Url"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
width = try container.decodeIfPresent(CGFloat.self, forKey: .width) ?? 0.0
height = try container.decodeIfPresent(CGFloat.self, forKey: .height) ?? 0.0
url = try container.decodeIfPresent(String.self, forKey: .url) ?? ""
}
func encode(to encoder: Encoder) throws {
}
}
然后:
if let data = self.data {
if let decoded = try? jsonDecoder.decode(JSONStructure.self, from: data) {
print("Decoded : \(decoded)")
self.images = decoded.images
}
}
日志:
解码:JSONStructure(图片:[DreamSiteradio.Images(宽度:800.0, 身高:590.0,网址:" https://obfuscated.image.url/image1.jpg"), DreamSiteradio.Images(宽度:800.0,高度:533.0,网址: " https://obfuscated.image.url/image2.jpg&#34), DreamSiteradio.Images(宽度:800.0,高度:478.0,网址: " https://obfuscated.image.url/image3.jpg&#34)])
答案 1 :(得分:1)
您可以创建2个结构而不是1来解析完整的响应,即
struct Response: Codable
{
let images: [Image]?
enum CodingKeys: String, CodingKey
{
case images = "Images"
}
}
struct Image : Codable
{
var width: CGFloat?
let height: CGFloat?
let url: String?
enum CodingKeys: String, CodingKey
{
case width = "Width"
case height = "Height"
case url = "Url"
}
}
由于响应中存在嵌套级别,因此我创建了多个结构。
此外,您不需要编写显式容器来进行解析。 Codable
会自行完成。
您只需使用以下代码解析样本JSON
if let data = jsonStr.data(using: .utf8)
{
let response = try? JSONDecoder().decode(Response.self, from: data)
print(response?.images)
}