在创建Mapbox MGLShape之前验证geojson

时间:2019-02-17 09:49:40

标签: ios swift mapbox mapbox-ios

我正在使用iOS Mapbox SDK通过来自第三方API的goejson MGLShapeCollectionFeature数据创建FeatureCollection

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

问题是,API有时会返回无效的geojson,其中单个Feature不包含有效坐标(请参见下文),并且初始化MGLShape失败并显示正确的'NSInvalidArgumentException', reason: 'A multipoint must have at least one vertex.'

除了手动解析和修复geojson之外,是否有办法过滤掉Features中无效的FeatureCollection

{
  "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
            ]
          ]
        ]
      }
    }
  ]
}

2 个答案:

答案 0 :(得分:4)

可能的解决方案是将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) } 的JSON解码为结构,过滤空项目,然后将对象编码回去:

<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class master extends FormRequest
{

    Route::get('/home','mastercontroller@index');
    Route::get('/lina','mastercontroller@index');
    Route::get('/love','mastercontroller@index');
    /**
    * Determine if the user is authorized to make this request.
    *
    * @return bool
    */
    public function authorize()
    {
        return true;
    }
    /**
    * Get the validation rules that apply to the request.
    *
    * @return array
    */
    public function rules()
    {
        return [
            //
        ];
    }
}

答案 1 :(得分:1)

如您所建议,我自己进行了过滤,并在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
    }
}