问题描述
我的 json 响应中有这样的字段:
"title": [2402,"Dr.","Prof.","Prof. Dr.","HM"]
我想解析它。我有我的模型类:
struct AppDataModel:Decodable {
...
let title = Dictionary<String,Any>()
enum CodingKeys: String,CodingKey{
case title
...
}
...
}
如您所见,我尝试使用 Dictionary<String,Any>()
。而且我还考虑过 Any -> [Any]
的数组,但我通常会收到这样的错误:
Type 'AppDataModel' does not conform to protocol 'Decodable'
我认为我必须像处理普通json一样处理它。但是我在 Swift 中没有找到这样的数据类型,只有字典。那么,也许有人知道如何处理这样的响应字段?
解决方法
struct AppDataModel: Codable {
let title: [Title]?
}
extension AppDataModel {
init(data: Data) throws {
self = try newJSONDecoder().decode(AppDataModel.self,from: data)
}
init(_ json: String,using encoding: String.Encoding = .utf8) throws {
guard let data = json.data(using: encoding) else {
throw NSError(domain: "JSONDecoding",code: 0,userInfo: nil)
}
try self.init(data: data)
}
init(fromURL url: URL) throws {
try self.init(data: try Data(contentsOf: url))
}
func with(
title: [Title]?? = nil
) -> AppDataModel {
return AppDataModel(
title: title ?? self.title
)
}
func jsonData() throws -> Data {
return try newJSONEncoder().encode(self)
}
func jsonString(encoding: String.Encoding = .utf8) throws -> String? {
return String(data: try self.jsonData(),encoding: encoding)
}
}
enum Title: 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(Title.self,DecodingError.Context(codingPath: decoder.codingPath,debugDescription: "Wrong type for Title"))
}
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)
}
}
}
func newJSONDecoder() -> JSONDecoder {
let decoder = JSONDecoder()
if #available(iOS 10.0,OSX 10.12,tvOS 10.0,watchOS 3.0,*) {
decoder.dateDecodingStrategy = .iso8601
}
return decoder
}
func newJSONEncoder() -> JSONEncoder {
let encoder = JSONEncoder()
if #available(iOS 10.0,*) {
encoder.dateEncodingStrategy = .iso8601
}
return encoder
}
//use
do {
let appDataModel = try AppDataModel(json)
}
catch{
//handle error
}