在Swift4中使用URLSession和JSONDecode丢失数据

时间:2017-11-28 21:26:13

标签: json decode nsurlsession swift4

使用Swift4,iOS11.1,Xcode9.1,

以下parseData方法几乎可以正常工作。一切似乎都运行良好(此URLSession和JSONDecode提取了正确的JSON数据集。)

然而,真正令我惊讶的是,普通浏览器显示不同的JSON数据(即,与此iOS-URLSession方法相比,获取的数量是20倍)。为什么???

在下面的代码中,您可以找到两个打印语句。第一个显示实际的URLRequest-string(包括所有查询和类型参数)。第二个打印获取的JSON数据集的数量。

如果您使用浏览器并使用完全相同的URLRequest-string获取JSON,则数据集的数量为20集。使用URLSession只有1套

为什么JSON数据长度的这种差异传递了??????????

这是PRINT_LOG 1:

https://maps.googleapis.com/maps/api/place/textsearch/json?query=Cham,%20Langackerstrasse&type=bus_station&key=AIzaSyDYtkKiJRuJ9tjkeOtEAuEtTLp5a0XR1M0

(API key no longer valid - after having found the solution, I did change the API-key for security reasons. The Question and its Answer are still of value tough).

这是PRINT_LOG 2:

count = 1

这是我的代码:

func parseData(queryString: String) {

    // nested function
    func createURLWithComponents() -> URL? {
        let urlComponents = NSURLComponents()
        urlComponents.scheme = "https";
        urlComponents.host = "maps.googleapis.com";
        urlComponents.path = "/maps/api/place/textsearch/json";
        // add params
        urlComponents.queryItems = [
            URLQueryItem(name: "query", value: "Cham, Langackerstrasse"),
            URLQueryItem(name: "type", value: "bus_station"),
            URLQueryItem(name: "key", value: AppConstants.GOOGLE_MAPS_DIRECTIONS_API_KEY)
        ]

        return urlComponents.url
    }

    let myUrl = createURLWithComponents()
    var myRequest = URLRequest(url: myUrl!)
    myRequest.httpMethod = "GET"
    myRequest.setValue("application/json; charset=UTF-8", forHTTPHeaderField: "Content-Type")

    let myConfiguration = URLSessionConfiguration.default
    let session = URLSession(configuration: myConfiguration, delegate: nil, delegateQueue: OperationQueue.main)

    // Until here everything all right !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    // i.e. the following print is correct !!!!!!!!!!!!!!!!!!!!!!!!!
    // (and when this print is copied to a Browser then the data fetched has 20 JSON-entries...)
    // PRINT_LOG 1
    print(myRequest.description)

    let myTask = session.dataTask(with: myRequest) { (data, response, error) in

        if (error != nil) {
            print("Error1 fetching JSON data")
        }
        else {
            do {
                //Decode retrived data with JSONDecoder and assing type of Station object
                let stationData = try JSONDecoder().decode(Station.self, from: data!)

                // Here is the puzzling thing to happen !!!!!!!!!!!!!!!!!!!!!!
                // i.e. the following print reveals count = 1 !!!!!!!!!!!!!!!!!
                // ??? Why not 20 as with the Browser ????????????????????
                // PRINT_LOG 2
                print("count = " + "\(String(describing: stationData.results.count))")
            }
            catch let error {
                print(error)
            }
        }
    }
    myTask.resume()
}

为了完整性,这里是匹配的Struct:

struct Station: Codable {

    let htmlAttributions: [String]
    let nextPageToken: String?
    let results: [Result]
    let status: String

    struct Result: Codable {
        let formattedAddress: String
        let geometry: Geometry
        let icon: String
        let id: String
        let name: String
        let photos: [Photo]?
        let placeID: String
        let rating: Double?
        let reference: String
        let types: [String]

        struct Geometry: Codable {
            let location: Coordinates
            let viewport: Viewport

            struct Coordinates: Codable {
                let lat: Double
                let lng: Double
                init(from decoder: Decoder) throws {
                    let values = try decoder.container(keyedBy: CodingKeys.self)
                    lat = try values.decode(Double.self, forKey: .lat)
                    lng = try values.decode(Double.self, forKey: .lng)
                }
                enum CodingKeys : String, CodingKey {
                    case lat
                    case lng
                }
            }

            struct Viewport: Codable {
                let northeast: Coordinates
                let southwest: Coordinates

                enum CodingKeys : String, CodingKey {
                    case northeast
                    case southwest
                }
            }

            enum CodingKeys : String, CodingKey {
                case location
                case viewport
            }
        }

        struct Photo: Codable {

            let height: Int
            let htmlAttributions: [String]
            let photoReference: String?
            let width: Int
            enum CodingKeys : String, CodingKey {
                case height
                case htmlAttributions = "html_attributions"
                case photoReference = "photo_reference"
                case width
            }
        }

        enum CodingKeys : String, CodingKey {
            case formattedAddress = "formatted_address"
            case geometry
            case icon
            case id
            case name
            case photos
            case placeID = "place_id"
            case rating
            case reference
            case types
        }
    }

    enum CodingKeys : String, CodingKey {
        case htmlAttributions = "html_attributions"
        case nextPageToken = "next_page_token"
        case results
        case status
    }
}

感谢您提供任何帮助。

1 个答案:

答案 0 :(得分:0)

找到它!!!

缺少Info.plist本地化! (即我在运行 - &gt;选项 - &gt;应用语言)下运行了将语言设置为德语的应用程序表单XCode。我的Info.plist只是部分本地化的(即我的文件<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script> <div id="app"> <div v-if="booleano">Yes</div> <div v-else>No</div> </div>只有几个条目 - 但不是完整的翻译)。这个缺失的翻译导致了这个问题!!!!

以纯英文运行它可以正常工作,我按预期得到20个条目。