这是该课程的简化版本:
class Movie: Codable {
var name: String
var genre: MovieGenre
init(name: String, genre: MovieGenre) {
self.name = name
self.genre = genre
}
}
enum MovieGenre: String, Codable {
case action
case drama
case horror
}
还有JSON:
{
"name" : "Test",
"genre" : 1
}
我知道JSON风格值和MovieGenre
枚举之间的关系是:
1 = action
2 = drama
3 = horror
如何使用JSONDecoder
将JSON风格Int值转换为枚举MovieGenre
?
我不想写init from decoder
,因为必须手动转换每个属性非常冗长。
这是一个例子:
let movie = Movie(name: "Test", genre: .action)
let jsonEncoder = JSONEncoder()
let jsonDecoder = JSONDecoder()
do {
// encoding
let jsonData = try jsonEncoder.encode(movie)
let jsonString = String(data: jsonData, encoding: .utf8)
print("JSON String : " + jsonString!) // prints: JSON String : {"name":"Test","genre":"action"}
// decoding
let json = "{\"name\":\"Test\",\"genre\":1}".data(using: .utf8)!
_ = try jsonDecoder.decode(Movie.self, from: json)
} catch {
print(error) // prints: typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "genre", intValue: nil)], debugDescription: "Expected to decode String but found a number instead.", underlyingError: nil))
}
答案 0 :(得分:0)
您的枚举类型与JSON中的类型不匹配。
我将您的枚举的类型更改为Int并设置操作的初始值(默认值为0),并且无需进行自定义解码即可获得预期的结果。
在操场上尝试:
import UIKit
import PlaygroundSupport
let jsonData = """
{
"name" : "Test",
"genre" : 1
}
""".data(using: .utf8)!
class Movie: Codable {
var name: String
var genre: MovieGenre
init(name: String, genre: MovieGenre) {
self.name = name
self.genre = genre
}
}
enum MovieGenre: Int, Codable {
case action = 1
case drama
case horror
}
let decoder = JSONDecoder()
let result = try? decoder.decode(Movie.self, from: jsonData)
print(result?.name)
print(result?.genre)
print(result?.genre.rawValue)
输出为:
可选(“测试”)
可选(__lldb_expr_39.MovieGenre.action)
可选(1)
这也应该以相同的方式编码。