Swift 5 Разбор многоуровневого JSONIOS

Программируем под IOS
Ответить
Anonymous
 Swift 5 Разбор многоуровневого JSON

Сообщение Anonymous »

Я все еще учусь, поэтому буду очень признателен за любую помощь.
Я пытаюсь проанализировать файл JSON, но, похоже, у меня ничего не получается. Просмотрел несколько онлайн-руководств, но не могу найти ни одного для такого типа дерева JSON.
Вот структура JSON:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"id": "zone_restrictionate_uav.2120",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
24.98812963,
44.10877275
],
[
24.98806588,
44.1070722
],
[
24.98537796,
44.10717296
],
[
24.9854417,
44.10887351
],
[
24.98812963,
44.10877275
]
]
]
},
"geometry_name": "the_geom",
"properties": {
"zone_id": "RZ 2120",
"human_readable_definition": "POLYGON: 440631.5819N 0245917.2667E- 440625.4599N 0245917.0372E- 440625.8227N 0245907.3606E- 440631.9446N 0245907.5901E- 440631.5819N 0245917.2667E",
"wkt": "POLYGON((24.9881296281 44.1087727458,24.9880658794 44.1070721972,24.9853779561 44.1071729596,24.9854417047 44.1088735083,24.9881296281 44.1087727458))",
"lower_lim": "GND",
"upper_lim": "120m AGL",
"contact": "mailto: aerofoto@mapn.ro",
"status": "RESTRICTED"
}
},
{
"type": "Feature",
"id": "zone_restrictionate_uav.2121",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
26.44760265,
44.13453494
],
[
26.43440247,
44.11089351
],
[
26.38955244,
44.1359355
],
[
26.40275262,
44.15957693
],
[
26.44760265,
44.13453494
]
]
]
},
"geometry_name": "the_geom",
"properties": {
"zone_id": "RZ 2121",
"human_readable_definition": "POLYGON: 440804.3258N 0262651.3695E- 440639.2166N 0262603.8489E- 440809.3678N 0262322.3888E- 440934.4769N 0262409.9094E- 440804.3258N 0262651.3695E",
"wkt": "POLYGON((26.4476026463 44.1345349397,26.4344024672 44.1108935127,26.3895524427 44.1359355018,26.4027526218 44.1595769288,26.4476026463 44.1345349397))",
"lower_lim": "GND",
"upper_lim": "120m AGL",
"contact": "mailto: aerofoto@mapn.ro",
"status": "RESTRICTED"
}
}
],
"totalFeatures": 339,
"numberMatched": 339,
"numberReturned": 339,
"timeStamp": "2021-08-15T11:39:26.055Z"
}

Я пытаюсь получить координаты с уровня дерева геометрии, а также данные с уровня свойств, которые я буду использовать для аннотирования карты, но до тех пор мне просто нужно распечатайте эту информацию.
На данный момент у меня есть следующие структуры и функции:
struct Notam: Decodable {
let type: String
let features: [Feature]
let totalFeatures: Int
let numberMatched: Int
let numberReturned: Int
let timeStamp: String
}

struct Feature: Decodable {
let type: String
let id: String
let geometry: [Geometry]
let geometry_name: String
let properties: [Properties]
}

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

struct Properties: Decodable {
let zone_id: String
let wkt: String
let contact: String
}

import SwiftUI

struct ContentView: View {
var body: some View {
Text("Hello World")
.onAppear(perform: readFile)
}

private func readFile() {
if let url = URL(string: "https://www.yeltsy.com/wp-content/uploa ... tions.json"),
let data = try? Data(contentsOf: url) {
let decoder = JSONDecoder()

if let jsonData = try? decoder.decode(Notam.self, from: data) {
print(jsonData.totalFeatures)
}
}
}
}

Приведенный выше код работает, если я комментирую константы геометрии и свойств структуры Feature
ОБНОВЛЕНИЕ 180821:
Благодаря комментарию @vadian я узнал о декодере geoJson, поэтому собираюсь опубликовать свой код, который анализирует geoJson и показывает наложения полигонов на карте, если это кому-то понадобится.< /p>
Сейчас я пытаюсь найти решение, как отображать аннотации (проверьте функцию decodeAnnotations() ниже) на карте, когда пользователь касается наложенного многоугольника. Было бы проще, если бы были точечные аннотации с местоположением. Но я не знаю, как их показать, если это наложение многоугольника. Если у кого-нибудь есть подсказка, дайте мне знать.
import SwiftUI
import MapKit
import CoreLocation

// All Map Data Goes here...

class MapViewModel: NSObject, ObservableObject, CLLocationManagerDelegate {

@Published var mapView = MKMapView()

@Published var region: MKCoordinateRegion!

// Based on Location it Will set up

// Alert
@Published var permissionDenied = false

@Published var mapType: MKMapType = .standard

func updateMapType() {
if mapType == .standard {
mapType = .hybrid
mapView.mapType = mapType
}
else {
mapType = .standard
mapView.mapType = mapType
}
}

// Focus Location...
func focusLocation() {
guard let _ = region else {return}

mapView.setRegion(region, animated: true)
mapView.setVisibleMapRect(mapView.visibleMapRect, animated: true)
}

func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
// Checking User Permission for Location Sharing

switch manager.authorizationStatus {
case .denied:
// If request denied, alert the user ...
permissionDenied.toggle()
case .notDetermined:
//If not determined, Request permission
manager.requestWhenInUseAuthorization()
case .authorizedWhenInUse:
manager.requestLocation()
manager.startUpdatingLocation()
default:
()
}
}

func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error.localizedDescription)
}

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// Getting user Region

guard let location = locations.last else {return}

self.region = MKCoordinateRegion(center: location.coordinate, span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5))

// Updating map
self.mapView.setRegion(self.region, animated: true)

//Smooth Animation..
self.mapView.setVisibleMapRect(self.mapView.visibleMapRect, animated: true)
manager.stopUpdatingLocation()

}

// Decode GeoJSON from the server
func showRestrictedZones(completion: @escaping ([MKOverlay]) -> ()) {
guard let url = URL(string: "https://www.yeltsy.com/wp-content/uploa ... tions.json") else {
fatalError("Unable to get geoJSON") }

downloadData(fromURL: url) { (returnedData) in
if let data = returnedData {
var geoJson = [MKGeoJSONObject]()
do {
geoJson = try MKGeoJSONDecoder().decode(data)
} catch {
fatalError("Unable to decode GeoJSON")
}
var overlays = [MKOverlay]()
for item in geoJson {
if let feature = item as? MKGeoJSONFeature {
for geo in feature.geometry {
if let polygon = geo as? MKPolygon {
overlays.append(polygon)
}
}
}
}
DispatchQueue.main.async {
completion(overlays)
}
}
}
}

func decodeAnnotations() {
guard let url = URL(string: "https://flightplan.romatsa.ro/init/stat ... e_uav.json") else {
fatalError("Unable to get geoJSON") }
downloadData(fromURL: url) { (returnedData) in
if let jsonData = returnedData {
do {
let result = try JSONDecoder().decode(FeatureCollection.self, from: jsonData)
for feature in result.features {
print(feature.properties.contact)
}
} catch { print("Error while parsing: \(error)") }
}
}
}

func downloadData( fromURL url: URL, completion: @escaping (_ data: Data?) -> ()) {
URLSession.shared.dataTask(with: url) { (data, response, error) in
guard
let data = data,
error == nil,
let response = response as? HTTPURLResponse,
response.statusCode >= 200 && response.statusCode < 300 else {
print("Error downloading data.")
completion(nil)
return
}
completion(data)
}
.resume()
}
}

import SwiftUI
import MapKit

struct MapView: UIViewRepresentable {

@EnvironmentObject var mapData: MapViewModel

@State var restrictions: [MKOverlay] = []

func makeCoordinator() -> Coordinator {
return MapView.Coordinator()
}

func makeUIView(context: Context) -> MKMapView {

let view = mapData.mapView

view.showsUserLocation = true
view.delegate = context.coordinator

mapData.showRestrictedZones { (restrictions) in
self.restrictions = restrictions
view.addOverlays(self.restrictions)
}

return view
}

func updateUIView(_ uiView: MKMapView, context: Context) {

}

class Coordinator: NSObject, MKMapViewDelegate {

func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let polygon = overlay as? MKPolygon {
let renderer = MKPolygonRenderer(polygon: polygon)
renderer.fillColor = UIColor.purple.withAlphaComponent(0.2)
renderer.strokeColor = .purple.withAlphaComponent(0.7)

return renderer

}
return MKOverlayRenderer(overlay: overlay)
}
}
}

import SwiftUI
import CoreLocation

struct Home: View {

@StateObject var mapData = MapViewModel()
// Location Manager..
@State var locationManager = CLLocationManager()

var body: some View {
ZStack{
MapView()
.environmentObject(mapData)
.ignoresSafeArea(.all, edges: .all)

VStack {
Spacer()

VStack{

Button(action: mapData.focusLocation, label: {
Image(systemName: "location.fill")
.font(.title2)
.padding(10)
.background(Color.white)

})

Divider()
.frame(width: 20)

Button(action: mapData.updateMapType, label: {
Image(systemName: mapData.mapType == .standard ? "network" : "map.fill")
.font(.title2)
.padding(10)
.background(Color.white)

})
}
.background(Color.white)
.cornerRadius(10)
.frame(maxWidth: .infinity, alignment: .trailing)
.shadow(color: Color.black.opacity(0.2), radius: 5, x: 0, y: 5)
.padding()
}
}
.onAppear(perform: {
locationManager.delegate = mapData
locationManager.requestWhenInUseAuthorization()
})
.alert(isPresented: $mapData.permissionDenied, content: {
Alert(title: Text("Permission Denied"), message: Text("Please Enable Permission In App Settings"), dismissButton: .default(Text("Go To Settings"), action: {
// Redirecting user to the settings...
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)
}))
})
}
}


Подробнее здесь: https://stackoverflow.com/questions/687 ... level-json
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»