我正在使用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
]
]
]
}
}
]
}
答案 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
}
}