如何以正确的方式在 IOS SWIFT 3 中解析 Google 距离矩阵 API JSON
Posted
技术标签:
【中文标题】如何以正确的方式在 IOS SWIFT 3 中解析 Google 距离矩阵 API JSON【英文标题】:How to parse Google Distance Matrix API JSON in IOS SWIFT 3 the correct way 【发布时间】:2017-07-03 07:06:17 【问题描述】:为了快速正确解析多维 JSON 数组,我进行了很多搜索。从搜索结果中,我可以理解的是,它有点类似于 android 中的 Retro-fit 解析。即为每个 json 响应创建一个解析类。如果我犯了错误,请原谅。我是ios swif的新手。
这是我的远程呼叫的距离矩阵 api json 输出
"destination_addresses" : [ "My Destination" ],
"origin_addresses" : [
"My Source"
],
"rows" : [
"elements" : [
"distance" :
"text" : "23.3 km",
"value" : 23333 //lastly i take this
,
"duration" :
"text" : "49 mins",
"value" : 2938
,
"status" : "OK" //then i check this
]
],
"status" : "OK" //first i check this
我是这样做的
这是我的 api 调用(工作正常)
http://maps.googleapis.com/maps/api/distancematrix/json?origins=latitude,longitude&destinations=latitude,longitude&mode=driving&language=en-EN&sensor=false
func extract_Validate(jsonData:NSData)
var distInMeters = 0
var chkVarOne = "notOK"
let json1 = NSString(data: jsonData as Data, encoding: String.Encoding.utf8.rawValue)
let data = json1!.data(using: String.Encoding.utf8.rawValue, allowLossyConversion: false)
print(data!)
do
print("Inside do")
let json = try JSONSerialization.jsonObject(with: jsonData as Data, options:.allowFragments) as! NSObject
if let dictionary = json as? [String: Any]
print("inside dictionary ")
if let detailsDict = dictionary as? NSDictionary
print("Parse Data")
for (key, value) in detailsDict
print("Property: \"\(key as! String)\"")
if key as! String == "status" && value as! String == "OK"
chkVarOne = "OK"
if chkVarOne == "OK"
if key as! String == "rows"
if let elementsDict = value as? NSDictionary
for(keyEle, valueEle) in elementsDict
if let elementsDict = value as? NSArray
if let array = elementsDict as? [Any]
if let firstObject = array.first
if let distanceSet = firstObject as? NSDictionary
for(keyDis, valueDis) in distanceSet
// print("Property: \"\(keyDis as! String)\"")
if keyDis as! String == "elements"
if let DistDict = valueDis as? NSDictionary
for(keyDict, valueDict) in DistDict
print("Property: \"\(keyDict as! String)\"")
if let DistDict = valueDis as? NSArray
// print(DistDict)
if let distArr = DistDict as?[Any]
if let frst = distArr.first
//print(frst)
if let distOne = frst as? NSDictionary
var checkvar = "notOK"
for(ketOneDis, valOneDis) in distOne
// print("Property: \"\(ketOneDis as! String)\"", valOneDis)
if ketOneDis as! String == "status" && valOneDis as! String == "OK"
checkvar = "OK"
if checkvar == "OK"
if ketOneDis as! String == "distance"
// print(valOneDis)
if let valtwoDis = valOneDis as? NSDictionary
for(kDis, vDis) in valtwoDis
// print("Property: \"\(kDis as! String)\"", vDis)
if kDis as! String == "value"
distInMeters = vDis as! Int
if let valTwoDis = valOneDis as? NSArray
print(valTwoDis)
//print(distanceSet,"rttgtgtgtgtgtgtg")
if let distSet = firstObject as? NSArray
print(distSet,"dfdffddfdfdfd")
//let rows
//ending here
catch
print("error in JSONSerialization")
print(distInMeters," is the resulting value")
此代码运行良好。但我知道这不是这样做的方法。
所以请帮帮我
我认为此代码稍后可能会出现一些错误。不太清楚
【问题讨论】:
【参考方案1】:最简单、最有效的方法是使用对象映射。像 Gloss (https://github.com/hkellaway/Gloss) 这样的东西就可以了。在您的情况下,您将拥有以下类(对象):
回应
import Foundation
import Gloss
//MARK: - Response
public struct Response: Glossy
public let destinationAddresses : [String]!
public let originAddresses : [String]!
public let rows : [Row]!
public let status : String!
//MARK: Decodable
public init?(json: JSON)
destinationAddresses = "destination_addresses" <~~ json
originAddresses = "origin_addresses" <~~ json
rows = "rows" <~~ json
status = "status" <~~ json
//MARK: Encodable
public func toJSON() -> JSON?
return jsonify([
"destination_addresses" ~~> destinationAddresses,
"origin_addresses" ~~> originAddresses,
"rows" ~~> rows,
"status" ~~> status,
])
元素:
import Foundation
import Gloss
//MARK: - Element
public struct Element: Glossy
public let distance : Distance!
public let duration : Distance!
public let status : String!
//MARK: Decodable
public init?(json: JSON)
distance = "distance" <~~ json
duration = "duration" <~~ json
status = "status" <~~ json
//MARK: Encodable
public func toJSON() -> JSON?
return jsonify([
"distance" ~~> distance,
"duration" ~~> duration,
"status" ~~> status,
])
行:
import Foundation
import Gloss
//MARK: - Row
public struct Row: Glossy
public let elements : [Element]!
//MARK: Decodable
public init?(json: JSON)
elements = "elements" <~~ json
//MARK: Encodable
public func toJSON() -> JSON?
return jsonify([
"elements" ~~> elements,
])
距离:
import Foundation
import Gloss
//MARK: - Distance
public struct Distance: Glossy
public let text : String!
public let value : Int!
//MARK: Decodable
public init?(json: JSON)
text = "text" <~~ json
value = "value" <~~ json
//MARK: Encodable
public func toJSON() -> JSON?
return jsonify([
"text" ~~> text,
"value" ~~> value,
])
创建类后,通过执行以下操作将 JSON 映射到 Object:
let jsonResponse = ..//Your JSON response
guard let distanceResponse = Response(json: jsonResponse) else
// handle decoding failure here
//You can use the distanceResponse object here as an object and access it's values.
在本教程中了解有关对象映射的更多信息:https://www.raywenderlich.com/150322/swift-json-tutorial-2
【讨论】:
我的问题是我们可以在没有任何其他库的帮助的情况下解析它吗?我的意思是像在android中一样? 当然可以,但不如使用对象映射有效。你最终会得到很多 if/guard 语句和 for 循环,这会导致错误(就像你拥有的代码一样)。 :-) 从 Swift 4 可以在没有其他库帮助的情况下解析 json。有可解码medium.com/swiftly-swift/…以上是关于如何以正确的方式在 IOS SWIFT 3 中解析 Google 距离矩阵 API JSON的主要内容,如果未能解决你的问题,请参考以下文章
在 iOS Swift 3 中以编程方式添加 Web 视图时如何在 UIWebView 中获取响应状态代码?
如何以编程方式从 iOS Swift 3 中的 XIB 推送和呈现给 UIViewController
如何使用 Swift 2 + XCode 7 + iOS 9 获取和解析 JSON [重复]