Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error batch-geocoding a single query #147

Closed
1ec5 opened this issue Jun 18, 2018 · 1 comment
Closed

Error batch-geocoding a single query #147

1ec5 opened this issue Jun 18, 2018 · 1 comment
Assignees
Labels

Comments

@1ec5
Copy link
Contributor

1ec5 commented Jun 18, 2018

If you call Geocoder.batchGeocode(_:completionHandler:), passing in a BatchGeocodeOptions that has only one coordinate or query, the following error results:

Error Domain=NSCocoaErrorDomain Code=4864 "Expected to decode Array<Any> but found a dictionary instead." UserInfo={NSCodingPath=(
), NSDebugDescription=Expected to decode Array<Any> but found a dictionary instead.}

The following code in Geocoder.urlForGeocoding(_:) assumes a batch geocode must have more than one query, which isn’t necessarily the case:

if options.queries.count > 1 {
mode = "mapbox.places-permanent"
assert(options.queries.count <= 50, "Too many queries in a single request.")
} else {
mode = "mapbox.places"
}

A single-query batch ends up requesting from the normal mapbox.places mode instead of mapbox.places-permanent. The two modes have different response formats, so a mapbox.places response ends up getting parsed unsuccessfully as a mapbox.places-permanent response.

Geocoder.urlForGeocoding(_:) shouldn’t hard-code modes like this; it should be up to the options object to determine the mode that gets inserted into the URL.

/cc @captainbarbosa

@captainbarbosa
Copy link
Contributor

captainbarbosa commented Jun 26, 2018

After inspecting this more with @1ec5 there seem to be some more interesting things going on:

The Mapbox Geocoding API returns different object types when batch geocoding one vs. many results, and it seems to be affecting how we parse out the responses. In this case, geocoding many addresses results in a returned array of many FeatureCollections.

On the other hand, when batch geocoding one query, one FeatureCollection object is returned. I would have expected a batch geocoding query with more than one query to return an object containing multiple FeatureCollections instead of an array of FeatureCollections.

Because of this, batchGeocodeWithOptions:completionHandler: calls a different part of the completion handler logic when performing the two types of batch geocoding queries:

open func batchGeocode(_ options: GeocodeOptions & BatchGeocodeOptions, completionHandler: @escaping BatchCompletionHandler) -> URLSessionDataTask {
        let url = urlForGeocoding(options)
        
        let task = dataTaskWithURL(url, completionHandler: { (data) in
            guard let data = data else { return }
            let decoder = JSONDecoder()
            
            do {
                let result = try decoder.decode([GeocodeResult].self, from: data)
                let placemarks = result.map { $0.placemarks }
                let attributionsByQuery = result.map { $0.attribution }
                completionHandler(placemarks, attributionsByQuery, nil)
                
            } catch {
                // ForwardBatchGeocodeOptions(query: "1 Main St")
                // ForwardBatchGeocodeOptions(queries: ["1 Main St"])
                completionHandler(nil, nil, error as NSError)
            }
            
        }) { (error) in
            // ForwardBatchGeocodeOptions(queries: ["1 Main St", "2 Main St"])
            completionHandler(nil, nil, error)
        }
        task.resume()
        return task
    }

Internally, it seems like for all three of these queries mentioned in the above comments return the same "Expected to decode Array<Any> but found a dictionary instead." error, so there is likely an issue with how we're deserializing the responses form the Geocoding API, and it may be that this object/array result difference from the Geocoding API could be one part of that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants