Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

404
Views
Validate geojson before creating a Mapbox MGLShape

I'm using the iOS Mapbox SDK to create a MGLShapeCollectionFeature from a goejson FeatureCollection data that comes from a 3rd party API.

guard let feature = try? MGLShape(data: jsonData, encoding: String.Encoding.utf8.rawValue) as? MGLShapeCollectionFeature else {
    print("Could not cast to specified MGLShapeCollectionFeature")
    return
}

The problem is that the API sometimes returns an invalid geojson where a single Feature does not contain valid coordinates (see below) and initialising the MGLShape fails with a 'NSInvalidArgumentException', reason: 'A multipoint must have at least one vertex.' which is correct.

Is there a way to filter out and drop those invalid Features within a FeatureCollection other that parsing and fixing the geojson manually?

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "icaoId": "KBOS",
        "airSigmetType": "AIRMET",
        "hazard": "IFR"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [

          ]
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "icaoId": "KSLC",
        "airSigmetType": "AIRMET",
        "hazard": "IFR"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -106.63,
              49.06
            ],
            [
              -104.12,
              48.95
            ],
            [
              -104.17,
              44.8
            ],
            [
              -106.91,
              46.38
            ],
            [
              -106.63,
              49.06
            ]
          ]
        ]
      }
    }
  ]
}
over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

A possible solution is to decode the JSON with Codable into structs, filter the empty items and encode the object back:

struct FeatureCollection : Codable {
    let type : String
    var features : [Feature]
}

struct Feature : Codable {
    let type : String
    let properties : Properties
    let geometry : Geometry
}

struct Properties : Codable {
    let icaoId, airSigmetType, hazard : String
}

struct Geometry : Codable {
    let type : String
    let coordinates : [[[Double]]]
}

do {
    var result = try JSONDecoder().decode(FeatureCollection.self, from: jsonData)
    let filteredFeatures = result.features.filter{$0.geometry.coordinates != [[]]}
    result.features = filteredFeatures
    let filteredData = try JSONEncoder().encode(result)
    guard let feature = try? MGLShape(data: filteredData, encoding: String.Encoding.utf8.rawValue) as? MGLShapeCollectionFeature else {
        print("Could not cast to specified MGLShapeCollectionFeature")
        return
    }
} catch {
    print(error)
}
over 4 years ago · Santiago Trujillo Report

0

As you suggested, I did the filtering myself and wrote this extension on Data

extension Data {

    func removeEmptyCoordinates() throws -> Data {
        guard var geojson = try JSONSerialization.jsonObject(with: self, options: []) as? [String: Any] else {
            return self
        }
        fix(geojson: &geojson,
            processFeatureIf: NSPredicate(format: "geometry.type == 'Polygon'"),
            keepFeatureIf: NSPredicate(format: "%K[0][SIZE] >= 2", "geometry.coordinates"))
        return try JSONSerialization.data(withJSONObject: geojson, options: [])
    }

    private func fix(geojson: inout [String: Any], processFeatureIf: NSPredicate, keepFeatureIf: NSPredicate) {
        guard let type = geojson["type"] as? String, type == "FeatureCollection" else {
            // "Not a FeatureCollection"
            return
        }
        // "No features to fix"
        guard let features = geojson["features"] as? [[String: Any]] else { return }

        let filtered = features.filter { feature in
            if !processFeatureIf.evaluate(with: feature) {
                // not processing
                return true
            }
            return keepFeatureIf.evaluate(with: feature)
        }
        geojson["features"] = filtered
    }
}
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!