mapbox / mapbox-gl-native

Interactive, thoroughly customizable maps in native Android, iOS, macOS, Node.js, and Qt applications, powered by vector tiles and OpenGL
https://mapbox.com/mobile
Other
4.37k stars 1.33k forks source link

Provide a GeoJSON serialization and deserialization utility #3630

Closed tobrun closed 7 years ago

tobrun commented 8 years ago

This is something that has already been discussed multiple times but was not ticketed out yet. Our SDK should expose an API so our users can work with GeoJSON.

Since those discussions, GeoJSON support has landed natively in https://github.com/mapbox/mapbox-gl-native/pull/2161. I'm not really sure how that translates to this requirement:

1ec5 commented 8 years ago

We could consider using a library like mattt/GeoJSONSerialization for iOS

GeoJSONSerialization converts GeoJSON into MapKit-specific types, which are incompatible with our iOS SDK. We could derive a Mapbox-compatible library from it, however.

friedbunny commented 8 years ago

Serializing JSON can be a definite pain (ugh, Swift), but there are a variety of third-party libraries out there for the folks who need to do it... so I'm not sure that we have to provide this ourselves for every user.

1ec5 commented 8 years ago

I can see the value-add for something like GeoJSONSerialization, though. Ordinary JSON comes with no semantics, so using a generic JSON library conjures up memories of raw XML parsing and validation using DTDs and XML Schemas. :grin: By contrast, a GeoJSON-specific library can convert to actual Mapbox SDK types.

For iOS, I think it makes more sense right now to have an independent GeoJSON-to-MGL* library rather than folding the APIs directly into the Mapbox iOS SDK. A developer using React Native Mapbox GL would want to use a more idiomatic React Native component anyways.

1ec5 commented 8 years ago

Note that basic GeoJSON support has landed in the native SDKs, in the form of GeoJSON sources and more-or-less GeoJSON-compatible geometry classes. This ticket remains open to track ideas for streamlining GeoJSON-related workflows. For example, a built-in GeoJSON (de)serialization feature (think MGLGeoJSONSerialization on iOS and macOS) is now eminently feasible.

tobrun commented 8 years ago

obsolete, closing

1ec5 commented 8 years ago

For iOS and macOS, an MGLGeoJSONSerialization utility would still be desirable. Reopening and removing the Android label.

1ec5 commented 7 years ago

Serialization and deserialization methods are being added in #7377. These methods live on MGLShape rather than a standalone MGLGeoJSONSerialization class, because deserializing a GeoJSON data object can only result in a kind of MGLShape, whereas NSJSONSerialization may return anything from a dictionary to a string (if fragments are allowed).

The methods being added in #7377 work with NSData objects containing GeoJSON string data, because working with data read in or being written out to a file is the most likely use case for this API. NSJSONSerialization can be composed with MGLShape methods to get Foundation-typed collection classes if needed, at a slight performance cost. If this cost turns out to be a problem, we can revisit adding additional methods to MGLShape to work with NSDictionary directly.

nitrag commented 7 years ago

Ok some of your conversation is over my head but just wanted to add my 2 cents.

Currently I'm appending data to the map as the user pans around.

  1. Ajax request to Server. GeoJSON response as STRING.
  2. Use SwiftyJSON to parse the String. Return (Swifty)JSON object.
  3. Retrieve GeoJSON source as (NS)Data. Convert it to (Swifty)JSON object. Loop through and merge the two JSON's into new a object. Return (NS)Data.
  4. Set the GeoJSON Source to the newly merged Data in Step 4.

It would be really cool to just be able to pass a GeoJSON string, with an optional append parameter set to true to the GeoJSON source. (append:false would replace)

geoJSONsource.setGeoJSON(string: geojsonString, append: true)

1ec5 commented 7 years ago

You'll need to call MGLShape(data:encoding:) to convert the new GeoJSON data (no need for SwiftyJSON) into an MGLShape. Then you can get the MGLShapeCollection (or MGLShapeCollectionFeature) stored in MGLShapeSource.shape, add to its list of shapes, and set MGLShapeSource.shape` to the modified collection.

Since this will be a common use case, we should have an example of it. /cc @friedbunny

1ec5 commented 7 years ago

Fixed in #7377 on the iOS SDK v3.4.0 release branch.