Swift 通用 Json 解析器
Swift Generic Json Parser
我有这个通用的 JSON 解析器可以解码数组
class JSONParserFromStruct {
typealias result<T> = (Result<[T], Error>) -> Void
func downloadList<T: Decodable>(of _: T.Type,
from data: Data,
completion: @escaping result<T>) {
do {
let decodedData: [T] = try! JSONDecoder().decode([T].self, from: data)
completion(.success(decodedData))
} catch {
completion(.failure(DataError.decodingError))
}
}
}
捆绑包中的这个 Users.json 文件
{
"name": "Taylor Swift"
}
这样称呼它:
func performRequest() {
let url = Bundle.main.url(forResource: "Users", withExtension: "json")!
let data = try! Data(contentsOf: url)
genericParser.downloadList(of: User.self, from: data) { result in
switch result {
case let .failure(error):
if error is DataError {
print("eroarea este: \(error.localizedDescription)")
print(url)
} else {
print("err is \(error.localizedDescription)")
}
print(error.localizedDescription)
case let .success(weather):
print(weather)
}
}
}
很有魅力
但是,当尝试使用另一个名为 Weather.json 的 json 文件时,失败并出现错误
"debugDescription: "Expected to decode Array but found a dictionary instead"
这是 json 我得到的错误是
{
"main": {
"temp": 281.52,
"feels_like": 278.99,
"temp_min": 280.15,
"temp_max": 283.71,
"pressure": 1016,
"humidity": 93
}
}
数据模型
struct Weather: Codable {
let main: Main
}
struct Main: Codable {
let temp: Double
}
...使用相同的 JSONParserFromStruct class,但它失败了。
是这样叫的
func performRequest() {
let url = Bundle.main.url(forResource: "Weather", withExtension: "json")!
let data = try! Data(contentsOf: url)
genericParser.downloadList(of: Weather.self, from: data) { result in
switch result {
case let .failure(error):
if error is DataError {
print("eroarea este: \(error.localizedDescription)")
print(url)
} else {
print("err is \(error.localizedDescription)")
}
print(error.localizedDescription)
case let .success(weather):
print(weather)
}
}
}
第一种情况有效,因为它是一个类似于
的数组
[
{
"name": "Taylor Swift"
}
]
第二种情况不是 {}
,因此您可以通过制作单个 T 而不是 [T][ 来轻松修复它=19=] 或将 json 包装成
[ {
"main": {
"temp": 281.52,
"feels_like": 278.99,
"temp_min": 280.15,
"temp_max": 283.71,
"pressure": 1016,
"humidity": 93
}
}
]
您的解析器不够通用,因为它只能解码数组。
泛型类型 T 可以是任何东西,单个对象也可以是数组,所以只需使用 T
class JSONParserFromStruct {
typealias ResultBlock<T> = (Result <T, Error>) -> Void
func downloadList<T: Decodable>(of type: T.Type,
from data: Data,
completion: @escaping ResultBlock<T>) {
do {
let decodedData: T = try JSONDecoder().decode(T.self, from: data)
completion(.success(decodedData))
}
catch {
completion(.failure(DataError.decodingError))
}
}
}
要解码 User
数组,请将数组指定为参数类型
genericParser.downloadList(of: [User].self, from: data)
现在
genericParser.downloadList(of: Weather.self, from: data)
应该有效
我有这个通用的 JSON 解析器可以解码数组
class JSONParserFromStruct {
typealias result<T> = (Result<[T], Error>) -> Void
func downloadList<T: Decodable>(of _: T.Type,
from data: Data,
completion: @escaping result<T>) {
do {
let decodedData: [T] = try! JSONDecoder().decode([T].self, from: data)
completion(.success(decodedData))
} catch {
completion(.failure(DataError.decodingError))
}
}
}
捆绑包中的这个 Users.json 文件
{
"name": "Taylor Swift"
}
这样称呼它:
func performRequest() {
let url = Bundle.main.url(forResource: "Users", withExtension: "json")!
let data = try! Data(contentsOf: url)
genericParser.downloadList(of: User.self, from: data) { result in
switch result {
case let .failure(error):
if error is DataError {
print("eroarea este: \(error.localizedDescription)")
print(url)
} else {
print("err is \(error.localizedDescription)")
}
print(error.localizedDescription)
case let .success(weather):
print(weather)
}
}
}
很有魅力
但是,当尝试使用另一个名为 Weather.json 的 json 文件时,失败并出现错误
"debugDescription: "Expected to decode Array but found a dictionary instead"
这是 json 我得到的错误是
{
"main": {
"temp": 281.52,
"feels_like": 278.99,
"temp_min": 280.15,
"temp_max": 283.71,
"pressure": 1016,
"humidity": 93
}
}
数据模型
struct Weather: Codable {
let main: Main
}
struct Main: Codable {
let temp: Double
}
...使用相同的 JSONParserFromStruct class,但它失败了。
是这样叫的
func performRequest() {
let url = Bundle.main.url(forResource: "Weather", withExtension: "json")!
let data = try! Data(contentsOf: url)
genericParser.downloadList(of: Weather.self, from: data) { result in
switch result {
case let .failure(error):
if error is DataError {
print("eroarea este: \(error.localizedDescription)")
print(url)
} else {
print("err is \(error.localizedDescription)")
}
print(error.localizedDescription)
case let .success(weather):
print(weather)
}
}
}
第一种情况有效,因为它是一个类似于
的数组[
{
"name": "Taylor Swift"
}
]
第二种情况不是 {}
,因此您可以通过制作单个 T 而不是 [T][ 来轻松修复它=19=] 或将 json 包装成
[ {
"main": {
"temp": 281.52,
"feels_like": 278.99,
"temp_min": 280.15,
"temp_max": 283.71,
"pressure": 1016,
"humidity": 93
}
}
]
您的解析器不够通用,因为它只能解码数组。
泛型类型 T 可以是任何东西,单个对象也可以是数组,所以只需使用 T
class JSONParserFromStruct {
typealias ResultBlock<T> = (Result <T, Error>) -> Void
func downloadList<T: Decodable>(of type: T.Type,
from data: Data,
completion: @escaping ResultBlock<T>) {
do {
let decodedData: T = try JSONDecoder().decode(T.self, from: data)
completion(.success(decodedData))
}
catch {
completion(.failure(DataError.decodingError))
}
}
}
要解码 User
数组,请将数组指定为参数类型
genericParser.downloadList(of: [User].self, from: data)
现在
genericParser.downloadList(of: Weather.self, from: data)
应该有效