Swift - 解码深度嵌套字典
Swift - Decoding a Deeply Nested Dictionary
我非常接近 - 但我正在努力使用一个非常简单的函数来允许我访问深深嵌套在我的 JSON 中的数据点。我使用的示例是 Google 方向 API.
示例JSON(来自 GMapsAPI):
{
"geocoded_waypoints" : [
{
"geocoder_status" : "OK",
"partial_match" : true,
"place_id" : "ChIJ960bMolw44kRQcGOlOZQ-r8",
"types" : [ "premise" ]
},
{
"geocoder_status" : "OK",
"partial_match" : true,
"place_id" : "EiMxMTggU2FsZW0gU3QsIEJvc3RvbiwgTUEgMDIxMTMsIFVTQSIaEhgKFAoSCSvDfDSJcOOJEbQanF0WxROfEHY",
"types" : [ "street_address" ]
}
],
"routes" : [
{
"bounds" : {
"northeast" : {
"lat" : 42.3647252,
"lng" : -71.0555085
},
"southwest" : {
"lat" : 42.3644965,
"lng" : -71.05552419999999
}
},
"copyrights" : "Map data ©2018 Google",
"legs" : [
{
"distance" : {
"text" : "82 ft",
"value" : 25
},
"duration" : {
"text" : "1 min",
"value" : 11
},
"end_address" : "118 Salem St, Boston, MA 02113, USA",
"end_location" : {
"lat" : 42.3647252,
"lng" : -71.0555085
},
"start_address" : "115 Salem St, Boston, MA 02113, USA",
"start_location" : {
"lat" : 42.3644965,
"lng" : -71.05552419999999
},
"steps" : [
{
"distance" : {
"text" : "82 ft",
"value" : 25
},
"duration" : {
"text" : "1 min",
"value" : 11
},
"end_location" : {
"lat" : 42.3647252,
"lng" : -71.0555085
},
"html_instructions" : "Head \u003cb\u003enorth\u003c/b\u003e on \u003cb\u003eSalem St\u003c/b\u003e toward \u003cb\u003eJerusalem Pl\u003c/b\u003e",
"polyline" : {
"points" : "ciqaG~_upLO?]A"
},
"start_location" : {
"lat" : 42.3644965,
"lng" : -71.05552419999999
},
"travel_mode" : "DRIVING"
}
],
"traffic_speed_entry" : [],
"via_waypoint" : []
}
],
"overview_polyline" : {
"points" : "ciqaG~_upLm@A"
},
"summary" : "Salem St",
"warnings" : [],
"waypoint_order" : []
}
],
"status" : "OK"
}
可解码结构:为此,我使用可解码。我已经能够访问第一级嵌套数据 (routes.summary),但我正在努力进一步深入(例如:routes.legs.duration)。我的代码结构如下:
struct Directions: Decodable {
let status: String
let routes: [Routes]
enum CodingKeys :String, CodingKey {
case status, routes
}
struct Routes: Decodable {
let summary: String
let legs: [Legs]
enum CodingKeys : String, CodingKey {
case summary, legs
}
}
struct Legs: Decodable {
let duration: Duration
enum CodingKeys : String, CodingKey {
case duration
}
}
struct Duration: Decodable {
let text: String
enum CodingKeys : String, CodingKey {
case text
}
}
URL设置后的实施:
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else { return }
do {
let directions = try
JSONDecoder().decode(Directions.self, from: data)
for item in directions.routes {
self.stringoutput = item.summary
}
毕竟,我想要做的就是能够在 JSON 和 return 中访问 "text" 那个值。最后一行代码是能够在return"summary"中成功JSON;我可以打印(方向),整个 array/dictionary 将 return 在调试区域,包括 "text"。但我还是不知道该怎么做:
x = 方向。routes.legs.duration.text
使 x 等于“1 分钟”
感谢任何人的帮助。
编辑:最终起作用的是下面 Vadian 的结构键和下面的 for in 循环:
for item in directions.routes {
print(item.summary)
self.direct = item.summary
for items in item.legs {
self.stringoutput = items.duration.text
print(items.duration.text)
}
干杯!
这些结构不会解码所有键,但它是一个起点。
如果键和结构成员同名则不需要指定CodingKeys
struct Directions: Decodable {
let status: String
let routes: [Route]
}
struct Route: Decodable {
let summary: String
let legs: [Leg]
}
struct Leg: Decodable {
let duration : TextValue
let distance : TextValue
let endAddress : String
let endLocation : Location
let startAddress : String
let startLocation : Location
let steps : [Step]
}
struct TextValue: Decodable {
let text: String
let value : Int
}
struct Location: Decodable {
let lat, lng : Double
}
struct Step: Decodable {
let duration : TextValue
let distance : TextValue
let endLocation : Location
let startLocation : Location
let htmlInstructions : String
let travelMode : String
}
要正确解码 snake_cased 密钥,您必须添加适当的密钥解码策略
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
要访问数组 ([]
),您必须按索引获取项目
step[0]
或者循环遍历数组
for step in steps {}
我非常接近 - 但我正在努力使用一个非常简单的函数来允许我访问深深嵌套在我的 JSON 中的数据点。我使用的示例是 Google 方向 API.
示例JSON(来自 GMapsAPI):
{
"geocoded_waypoints" : [
{
"geocoder_status" : "OK",
"partial_match" : true,
"place_id" : "ChIJ960bMolw44kRQcGOlOZQ-r8",
"types" : [ "premise" ]
},
{
"geocoder_status" : "OK",
"partial_match" : true,
"place_id" : "EiMxMTggU2FsZW0gU3QsIEJvc3RvbiwgTUEgMDIxMTMsIFVTQSIaEhgKFAoSCSvDfDSJcOOJEbQanF0WxROfEHY",
"types" : [ "street_address" ]
}
],
"routes" : [
{
"bounds" : {
"northeast" : {
"lat" : 42.3647252,
"lng" : -71.0555085
},
"southwest" : {
"lat" : 42.3644965,
"lng" : -71.05552419999999
}
},
"copyrights" : "Map data ©2018 Google",
"legs" : [
{
"distance" : {
"text" : "82 ft",
"value" : 25
},
"duration" : {
"text" : "1 min",
"value" : 11
},
"end_address" : "118 Salem St, Boston, MA 02113, USA",
"end_location" : {
"lat" : 42.3647252,
"lng" : -71.0555085
},
"start_address" : "115 Salem St, Boston, MA 02113, USA",
"start_location" : {
"lat" : 42.3644965,
"lng" : -71.05552419999999
},
"steps" : [
{
"distance" : {
"text" : "82 ft",
"value" : 25
},
"duration" : {
"text" : "1 min",
"value" : 11
},
"end_location" : {
"lat" : 42.3647252,
"lng" : -71.0555085
},
"html_instructions" : "Head \u003cb\u003enorth\u003c/b\u003e on \u003cb\u003eSalem St\u003c/b\u003e toward \u003cb\u003eJerusalem Pl\u003c/b\u003e",
"polyline" : {
"points" : "ciqaG~_upLO?]A"
},
"start_location" : {
"lat" : 42.3644965,
"lng" : -71.05552419999999
},
"travel_mode" : "DRIVING"
}
],
"traffic_speed_entry" : [],
"via_waypoint" : []
}
],
"overview_polyline" : {
"points" : "ciqaG~_upLm@A"
},
"summary" : "Salem St",
"warnings" : [],
"waypoint_order" : []
}
],
"status" : "OK"
}
可解码结构:为此,我使用可解码。我已经能够访问第一级嵌套数据 (routes.summary),但我正在努力进一步深入(例如:routes.legs.duration)。我的代码结构如下:
struct Directions: Decodable {
let status: String
let routes: [Routes]
enum CodingKeys :String, CodingKey {
case status, routes
}
struct Routes: Decodable {
let summary: String
let legs: [Legs]
enum CodingKeys : String, CodingKey {
case summary, legs
}
}
struct Legs: Decodable {
let duration: Duration
enum CodingKeys : String, CodingKey {
case duration
}
}
struct Duration: Decodable {
let text: String
enum CodingKeys : String, CodingKey {
case text
}
}
URL设置后的实施:
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else { return }
do {
let directions = try
JSONDecoder().decode(Directions.self, from: data)
for item in directions.routes {
self.stringoutput = item.summary
}
毕竟,我想要做的就是能够在 JSON 和 return 中访问 "text" 那个值。最后一行代码是能够在return"summary"中成功JSON;我可以打印(方向),整个 array/dictionary 将 return 在调试区域,包括 "text"。但我还是不知道该怎么做:
x = 方向。routes.legs.duration.text
使 x 等于“1 分钟”
感谢任何人的帮助。
编辑:最终起作用的是下面 Vadian 的结构键和下面的 for in 循环:
for item in directions.routes {
print(item.summary)
self.direct = item.summary
for items in item.legs {
self.stringoutput = items.duration.text
print(items.duration.text)
}
干杯!
这些结构不会解码所有键,但它是一个起点。
如果键和结构成员同名则不需要指定CodingKeys
struct Directions: Decodable {
let status: String
let routes: [Route]
}
struct Route: Decodable {
let summary: String
let legs: [Leg]
}
struct Leg: Decodable {
let duration : TextValue
let distance : TextValue
let endAddress : String
let endLocation : Location
let startAddress : String
let startLocation : Location
let steps : [Step]
}
struct TextValue: Decodable {
let text: String
let value : Int
}
struct Location: Decodable {
let lat, lng : Double
}
struct Step: Decodable {
let duration : TextValue
let distance : TextValue
let endLocation : Location
let startLocation : Location
let htmlInstructions : String
let travelMode : String
}
要正确解码 snake_cased 密钥,您必须添加适当的密钥解码策略
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
要访问数组 ([]
),您必须按索引获取项目
step[0]
或者循环遍历数组
for step in steps {}