我有下面的对象:
class Food {
var cal: Int
var displayName: String
var imgUrl: String
var dishType: DishType
init(cal: Int, displayName: String, imgUrl: String, dishType: DishType) {
self.cal = cal
self.displayName = displayName
self.imgUrl = imgUrl
self.dishType = dishtype
}
}
enum DishType {
case starter
case main
case desert
}
这是我的Alamofire请求的一部分:
if let cal = foodJson["cal"].int,
let displayName = foodJson["display_name"].string,
let dishType = foodJson["type"].string,
let imgUrl = foodJson["imgUrl"].string {
let food = Food(cal: cal, displayName: displayName, imgUrl: imgUrl, dishType: ??)
foods.append(food)
我如何将Json字符串“dishType”转换为用枚举创建的“DishType”类型,以便正确填充我的Food实例?
最佳答案
您可能想为您的枚举指定一个关联值:
enum DishType: String {
case starter = "starter"
case main = "main"
case desert = "desert"
}
或者,更简单地说:
enum DishType: String {
case starter
case main
case desert
}
然后,您可以执行以下操作:
dishType = DishType(rawValue: string)
例如
if let dishTypeString = foodJson["type"].string,
let dishType = DishType(rawValue: dishTypeString) {
...
}
就个人而言,如果使用Swift 4,我将退休
SwiftyJSON
并使用本机JSONDecoder
并将您的类型声明为Codable
。 (请注意,我们仍然需要定义DishType
以具有关联的值,如上所述)。例如,假设您的响应是这样的:
{
"foods": [{
"cal": 800,
"display_name": "Beef",
"imgUrl": "http://example.com/wheres_the_beef.jpg",
"dishType": "main"
},
{
"cal": 2000,
"display_name": "Chocolate cake",
"imgUrl": "http://example.com/yummy.jpg",
"dishType": "desert"
}
]
}
然后,您可以像这样定义类型:
struct Food: Codable {
let cal: Int
let displayName: String
let imgUrl: String
let dishType: DishType
}
enum DishType: String, Codable {
case starter
case main
case desert
}
然后您可以像这样解析响应:
struct FoodsResponse: Codable {
let foods: [Food]
}
Alamofire.request(url)
.responseData { response in
switch response.result {
case .success(let data):
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let responseObject = try decoder.decode(FoodsResponse.self, from: data)
print(responseObject.foods)
} catch {
print(error)
}
case .failure(let error):
print(error)
}
}
这使您完全不用手动遍历结果以将其映射到对象。
显然,我假设您的实际响应具有更多的键,而不仅仅是
foods
,因此您可以将所需的任何字段添加到FoodsResponse
,但是希望这可以说明让JSONDecoder
自动将JSON解析为模型结构的想法。有关
JSONDecoder
和Codable
类型的更多信息,请参见Encoding and Decoding Custom Types。顺便说一下,我的示例
FoodResponse
结构提示了一个问题,为什么我不仅仅假定Web服务将返回Food
对象的数组。让我解释一下我的理由。Web服务响应中的
FoodsResponse
的更典型结构是:struct FoodsResponse: Codable {
let success: Bool
let error: String? // only supplied if `success` was `false`
let foods: [Food]? // only supplied if `success` was `true`
}
在此结构中,此响应对象可以处理成功方案,例如:
{
"success": true,
"foods": [...]
}
或失败:
{
"success": false,
"error": "No data found"
}
我认为最好是包含一些常见的成功 bool(boolean) 值的结构,例如
success
,所有格式正确的响应都包含,然后分别填充了用于成功或失败的各种属性。