我必须对响应下载的这种JSON类型进行解码。 JSON是这样,我需要检索所有项目的“图库” JSON:https://pastebin.com/KnEwZzxd 我尝试了许多解决方案,但无法创建此儿子的解码。 我也将完整的代码发布在pastebin上。
{
"status": 200,
"data": {
"date": "2018-07-29T00:00:00.300Z",
"featured": [
{
"id": "5b56298d781e197186378f50",
"name": "Sun Tan Specialist",
"price": "1,500",
"priceIcon": "vbucks",
"priceIconLink": "https://image.fnbr.co/price/icon_vbucks.png",
"images": {
"icon": "https://image.fnbr.co/outfit/5b56298d781e197186378f50/icon.png",
"png": "https://image.fnbr.co/outfit/5b56298d781e197186378f50/png.png",
"gallery": "https://image.fnbr.co/outfit/5b56298d781e197186378f50/gallery.jpg",
"featured": "https://image.fnbr.co/outfit/5b56298d781e197186378f50/featured.png"
},
"rarity": "epic",
"type": "outfit",
"readableType": "Outfit"
},
{
"id": "5b562af2781e19db65378f5c",
"name": "Rescue Paddle",
"price": "800",
"priceIcon": "vbucks",
"priceIconLink": "https://image.fnbr.co/price/icon_vbucks.png",
"images": {
"icon": "https://image.fnbr.co/pickaxe/5b562af2781e19db65378f5c/icon.png",
"png": "https://image.fnbr.co/pickaxe/5b562af2781e19db65378f5c/png.png",
"gallery": "https://image.fnbr.co/pickaxe/5b562af2781e19db65378f5c/gallery.jpg",
"featured": false
},
"rarity": "rare",
"type": "pickaxe",
"readableType": "Pickaxe"
}
],
"daily": [
{
"id": "5ab1723e5f957f27504aa502",
"name": "Rusty Rider",
"price": "1,200",
"priceIcon": "vbucks",
"priceIconLink": "https://image.fnbr.co/price/icon_vbucks.png",
"images": {
"icon": "https://image.fnbr.co/glider/5ab1723e5f957f27504aa502/icon.png",
"png": "https://image.fnbr.co/glider/5ab1723e5f957f27504aa502/png.png",
"gallery": "https://image.fnbr.co/glider/5ab1723e5f957f27504aa502/gallery.jpg",
"featured": "https://image.fnbr.co/glider/5ab1723e5f957f27504aa502/featured.png"
},
"rarity": "epic",
"type": "glider",
"readableType": "Glider"
},
{
"id": "5b0e944bdb94f1a4bbc0a8e4",
"name": "Rambunctious",
"price": "500",
"priceIcon": "vbucks",
"priceIconLink": "https://image.fnbr.co/price/icon_vbucks.png",
"images": {
"icon": "https://image.fnbr.co/emote/5b0e944bdb94f1a4bbc0a8e4/icon.png",
"png": "https://image.fnbr.co/emote/5b0e944bdb94f1a4bbc0a8e4/png.png",
"gallery": "https://image.fnbr.co/emote/5b0e944bdb94f1a4bbc0a8e4/gallery.jpg",
"featured": false
}
]
}
}
答案 0 :(得分:1)
除了发布JSON
代码本身之外,实际显示尝试解码的方式也会很有用。^ _________ ^。
无论如何,解决此问题的最佳方法是使用自定义结构和Decodable Protocol
处理JSON
响应。
最初,您将从JSON
中获得两个值:
/// The Initial Response From The Server
struct Response: Decodable {
let status: Int
let data: ResponseData
}
然后我们将“数据”映射到名为ResponseData
的结构:
/// The Data Object
struct ResponseData: Decodable{
let date: String
let featured: [Product]
let daily: [Product]
}
在此,我们有两个variables
,其中包含一个我称为struct
的相同Product
数组:
/// The Product Structure
struct Product: Decodable{
let id: String
let name: String
let price: String
let priceIcon: String
let priceIconLink: String
let images: ProductImages
let rarity: String
let type: String
let readableType: String
}
在此范围内,我们有一个variable
,它是一个dictionary
(图像),然后我们将其映射到另一个struct
:
/// The Data From The Product Images Dictionary
struct ProductImages: Decodable{
let icon: String
let png: String
let gallery: String
///The Featured Variable For The Product Images Can Contain Either A String Or A Boolean Value
let featured: FeaturedType
}
ProductImages
的问题在于,精选的var
有时包含一个String
,但在其他情况下,它包含一个Bool
的值。因此,我们需要创建一个自定义结构来处理此解码,以确保我们总是得到String
(我可能做得不好,所以如果有人有更好的解决方案,请这样说):
/// Featured Type Returns A String Of Either The Boolean Value Or The Link To The JPG
struct FeaturedType : Codable {
let formatted: String
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
do {
//1. If We Get A Standard Response We Have A String
let stringResult = try container.decode(String.self)
formatted = stringResult
} catch {
//2. On Occassions We Get An Bool
let boolResult = try container.decode(Bool.self)
formatted = String(boolResult)
}
}
}
现在这是JSON
的基本结构,因此现在您需要处理它。在此示例中,由于我没有实际的JSON
,因此正在从MainBundle
加载URL
。
/// Loads & Decodes The JSON File
func retreiveJSON(){
//1. Load The JSON File From The Main Bundle
guard let jsonURL = Bundle.main.url(forResource: "sample", withExtension: ".json") else { return }
do{
//2. Get The Data From The URL
let data = try Data(contentsOf: jsonURL)
//3. Decode The JSON
let jsonData = try JSONDecoder().decode(Response.self, from: data)
//4. Extract The Data
extractDataFrom(jsonData)
}catch{
print("Error Processing JSON == \(error)")
}
}
在上面的函数中,您会注意到我正在调用函数extractDataFrom()
,该函数可让您随后执行需要处理的数据:
/// Extracts The Daily & Featured Products From The JSON
///
/// - Parameter jsonData: Response
func extractDataFrom(_ jsonData: Response){
//1. Get The Daily Products
let dailyProducts = jsonData.data.daily
dailyProducts.forEach { (product) in
print(product.id)
print(product.name)
print(product.price)
print(product.priceIcon)
print(product.priceIconLink)
print(product.images)
print(product.rarity)
print(product.type)
print(product.readableType)
}
//2. Get The Featured Products
let featuredProducts = jsonData.data.featured
featuredProducts.forEach { (product) in
print(product.id)
print(product.name)
print(product.price)
print(product.priceIcon)
print(product.priceIconLink)
print(product.images)
print(product.rarity)
print(product.type)
print(product.readableType)
}
}
如果您想保存此数据,则只需在类声明下添加以下变量,例如:
var featuredProducts = [Product]()
var dailyProducts = [Product]()
然后在extractDataFrom()函数中更改:
let dailyProducts
let featuredProducts
收件人:
dailyProducts = jsonData.data.daily
featuredProducts = jsonData.data.featured
请注意,这是一个非常粗糙的示例,并且如上所述,我可能未正确处理“功能”变量。
希望有帮助...
答案 1 :(得分:-1)
感谢quicktype和其他将有效json转换为Swift和其他语言的服务非常简单。根据您的需求进行编辑应该足够简单。
// To parse the JSON, add this file to your project and do:
//
// let welcome = try? JSONDecoder().decode(Welcome.self, from: jsonData)
import Foundation
struct Welcome: Codable {
let status: Int
let data: DataClass
}
struct DataClass: Codable {
let date: String
let featured, daily: [Daily]
}
struct Daily: Codable {
let id, name, price, priceIcon: String
let priceIconLink: String
let images: Images
let rarity, type, readableType: String?
}
struct Images: Codable {
let icon, png, gallery: String
let featured: Featured
}
enum Featured: Codable {
case bool(Bool)
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Bool.self) {
self = .bool(x)
return
}
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
throw DecodingError.typeMismatch(Featured.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Featured"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .bool(let x):
try container.encode(x)
case .string(let x):
try container.encode(x)
}
}
}