如何以正确的方式在 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

如何以编程方式从 iOS Swift 3 中的 XIB 推送和呈现给 UIViewController

如何使用 Swift 2 + XCode 7 + iOS 9 获取和解析 JSON [重复]

Swift之深入解析如何结合Core Data和SwiftUI

如何在 ios swift 中以编程方式创建自动布局等宽约束?