在本章中,你将学会如何引用并解析JSON
数据。
JSON
,是JavaScript
目标表示法的简称,是客户机和服务器应用程序中用于数据交换的一种常见数据格式。咱们App客户端发送网络请求,服务端就会回来JSON
文本,供App
客户端进行解析,解析完成后客户端再把对应数据展现到页面上。
咱们学习下JSON
数据及其解码办法的相关内容。
项目创立
首要,创立一个新的Playground
文件,命名为SwiftUIJSON
。
变量声明
咱们创立一个简略的json
数据。
let json = """
{
"name": "Ricardo",
"country": "China",
"city": "Guangzhou"
}
"""
然后,咱们界说下需求的参数称号,咱们需求新建一个personalInformation
个人信息的结构体来界说json
数据里的参数。
struct personalInformation: Codable {
var name: String
var country: String
var city: String
}
这儿,咱们运用的personalInformation
个人信息结构体需求遵从Codable
可编码协议,并且personalInformation
个人信息结构体中界说的变量需求与JSON
的键逐个匹配。
实例化
接下来,咱们解析下json
数据。
let decoder = JSONDecoder()
if let jsonData = json.data(using: .utf8) {
do {
let message = try decoder.decode(personalInformation.self, from: jsonData)
print(message)
} catch {
print(error)
}
}
咱们实例化JSONDecoder
的一个实例,然后将JSON
字符串转换为personalInformation
的目标。
运行下代码,咱们能够看到,咱们取得并展示了json
内的数据。
参数映射
在咱们从服务器取得JSON
数据时,可能会出现咱们实例化的参数和JSON
数据的参数不匹配的状况。
示例:在JSON
数据中,咱们把city
城市换成cityName
城市称号。
这时候,咱们就需求映射字段称号,而不需求每次都更改咱们界说的字段。
enum CodingKeys: String, CodingKey {
case name
case country
case city = "cityName"
}
咱们在personalInformation
个人信息结构体增加了一个枚举,然后运用case
转换参数进行映射。
目标嵌套
咱们再考虑一种状况,如果JSON数据中存在嵌套联系,比如咱们新增一个参数location
方位,在location
方位里放country
国家参数。
let json = """
{
"name": "Ricardo",
"location": {
"country": "China",
},
"cityName": "Guangzhou"
}
"""
这个例子很常见,咱们能够把省、市、区放在地址里,这种目标中嵌套目标,咱们处理也需求建立映射联系。
首要咱们需求在CodingKeys
中设置切换。
enum CodingKeys: String, CodingKey {
case name
case country = "location"
case city = "cityName"
}
同时咱们还需求界说了一个枚举LocationKeys
,它的参数是被location
方位嵌套的country
国家参数。
由于咱们不能直接映射,那咱们需求在Codable
协议的初始化器中来解码得到咱们想要的值。
enum LocationKeys: String, CodingKey {
case country
}
然后是实现办法。
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
name = try values.decode(String.self, forKey: .name)
let location = try values.nestedContainer(keyedBy: LocationKeys.self, forKey: .country)
country = try location.decode(String.self, forKey: .country)
city = try values.decode(String.self, forKey: .city)
}
咱们在init
函数办法中,调用decoder
的container
容器解码器办法来获取CodingKeys
枚举的数据,CodingKeys
枚举里有name
姓名。
而由于country
国家参数在location
方位的容器中,就需求通过调用LocationKeys
枚举的nestedContainer
办法进一步解码城市的值。
以上便是嵌套目标解码JSON
数据的办法。
数据数组
在上面咱们了解的都是根据1
行数据的解析,如果咱们JSON
数据是由多行数据
组成的数组,咱们又该如何解析呢?
let json = """
{
"messages":[
{
"name": "Ricardo",
"location": {
"country": "China",
},
"cityName": "Guangzhou"
},{
"name": "Ricardo",
"location": {
"country": "China",
},
"cityName": "Guangzhou"
}]
}
"""
咱们的JSON
有一个messages
数组,里边有2
个数据行。
要想解析这个messages
数组,咱们也是需求创立一个遵从Codable
可编码协议的结构体,这儿命名为MessageArrays
。
struct MessageArrays: Codable {
var messages: [personalInformation]
}
咱们用messages
来接纳personalInformation
个人信息结构体的数据。
然后在解析这块,咱们就不能直接解析personalInformation
的数据了,咱们改为解析MessageArrays
数组的数据。
同时,咱们用for
循环输出下数据看看效果:
let decoder = JSONDecoder()
if let jsonData = json.data(using: .utf8) {
do {
let messageArrays = try decoder.decode(MessageArrays.self, from: jsonData)
for message in messageArrays.messages {
print(message)
}
} catch {
print(error)
}
}
祝贺你,咱们完成了JSON
数据的全部学习!
完好代码
import SwiftUI
//json数据准备
let json = """
{
"messages":[
{
"name": "Ricardo",
"location": {
"country": "China",
},
"cityName": "Guangzhou"
},{
"name": "Ricardo",
"location": {
"country": "China",
},
"cityName": "Guangzhou"
}]
}
"""
//界说数组
struct MessageArrays: Codable {
var messages: [personalInformation]
}
//界说模型
struct personalInformation: Codable {
var name: String
var country: String
var city: String
//界说参数枚举
enum CodingKeys: String, CodingKey {
case name
case country = "location"
case city = "cityName"
}
//数组枚举
enum LocationKeys: String, CodingKey {
case country
}
//实例化
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
name = try values.decode(String.self, forKey: .name)
let location = try values.nestedContainer(keyedBy: LocationKeys.self, forKey: .country)
country = try location.decode(String.self, forKey: .country)
city = try values.decode(String.self, forKey: .city)
}
}
//解析数据
let decoder = JSONDecoder()
if let jsonData = json.data(using: .utf8) {
do {
let messageArrays = try decoder.decode(MessageArrays.self, from: jsonData)
for message in messageArrays.messages {
print(message)
}
} catch {
print(error)
}
}
快来动手试试吧!
如果本专栏对你有协助,不妨点赞、评论、重视~