0

I have tried many different ways from many different articles, but I just cannot decode this JSON from a HTTP response.

Can somebody help me please?

Thanks.

JSON: This is the JSON returned by Data URL:

{ "@odata.context": "$metadata#GeoFences(Points())", "value": [ { "ID": "69d5513c-c1f1-4f5d-aef5-184a913484be", "GEOFENCE_NAME": "Dragon Park", "GEOFENCE_TYPE": "C", "PRIVACY": "X", "CENTER_LAT": 32.92536134246622, "CENTER_LONG": -117.01864890726854, "ZOOM_LAT": 0.007421265080928663, "ZOOM_LONG": 0.006358979598971359, "PATH_TOLERANCE": 5, "ENTRANCE_TOLERANCE": 5, "Points": { "POINT_TYPE": "E", "POINT_NUM": 0, "LATITUDE": 32.924186548800414, "LONGITUDE": -117.0213193658842, "parent_ID": "69d5513c-c1f1-4f5d-aef5-184a913484be" } } ] } 

Structures: These are the strifes that I want to decode into. I am hoping for the Value structure with the embedded points structure.

struct Value: Decodable { let id: String? let geofenceName: String? let geofenceType: String? let privacy: String? let centerLat: Double? let centerLong: Double? let zoomLat: Double? let zoomLong: Double? let pathTolerance: Double? let entranceTolerance: Double? let points: GeoFencePointData enum CodingKeys: String, CodingKey { case id = "ID" case geofenceName = "GEOFENCE_NAME" case geofenceType = "GEOFENCE_TYPE" case privacy = "PRIVACY" case centerLat = "CENTER_LAT" case centerLong = "CENTER_LONG" case zoomLat = "ZOOM_LAT" case zoomLong = "ZOOM_LONG" case pathTolerance = "PATH_TOLERANCE" case entranceTolerance = "ENTRANCE_TOLERANCE" case points = "Points" } } struct GeoFencePointData: Codable { var pointType: String var pointNum: Int var latitude: Double var longitude: Double var parentID: String enum CodingKeys: String, CodingKey { case pointType = "POINT_TYPE" case pointNum = "POINT_NUM" case latitude = "LATITUDE" case longitude = "LONGITUDE" case parentID = "parent_ID" } } 

Swift Code: Seems like this is the typical code used to decode the JSON. I guess main complication is that the response is an array.

// Convert HTTP Response Data to a String if let data = data, let dataString = String(data: data, encoding: .utf8) { print("Response data string:\n \(dataString)") print("Data: \(data)") do { let decoder = JSONDecoder() let allGeoFences = try decoder.decode([Value].self, from: data) print(allGeoFences) } catch { print("error: \(error)") } } 
6
  • 1
    You are missing the top-level of your JSON. struct TopLevel: Codable { let value: [Value]} and then let topLevel = try decoder.decode([TopLevel].self, from: data); let allGeoFences = topLevel.value Commented Aug 21, 2020 at 17:59
  • 1
    Tip: Do the reverse, transform your struct into JSON, and compare the result. See there: stackoverflow.com/questions/63176406/… Since you wrote [Value].self, it means that you'll have a let values: [Value] = [Value(....)]: and convert that into JSON` Commented Aug 21, 2020 at 18:01
  • @Larme: I get this error when I try that: (You are missing the top-level of your JSON.) error: typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil)) Commented Aug 21, 2020 at 18:12
  • I copy/paste, sorry, I meant TopLevel.self, not [TopLevel].self. Commented Aug 21, 2020 at 18:13
  • @Larme: When I reverse engineer, can I ignore: {"@odata.context":"$metadata#GeoFences(Points())","value":? Thanks Commented Aug 21, 2020 at 18:17

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.