JSON parsing error - No value associated with key CodingKeys - json

So, I have tried looking for the answer, I have seen many questions similar to mine. I have tried adding an enum codingKey, I have tried reworking the JSON, but nothing seems to work. I know it's probably something very simple too. (I'm a noob.) Please help.
I am making a Quotes app as part of a project for a course I'm taking.
Here's the code for the Model:
import Foundation
class AllQuotes: Identifiable, Decodable {
var id:UUID?
var quoteTopic:String
var topicImage:String
var featured:Bool
var QuotesList:[Quotes]
}
class Quotes: Identifiable, Decodable {
var id:UUID?
var name:String
var actualQuote:String
var image:String?
private enum CodingKeys: String, CodingKey {
case id = "id"
case name = "name"
case actualQuote = "actualQuote"
case image = "image"
}
}
Here's my JSON code:
[
{
"quoteTopic": "Wise Quotes",
"topicImage": "wise quotes",
"featured": false,
"QuotesList": [
{
"name": "Lao Tzu",
"actualQuote": "The journey of a thousand miles begins with one step.",
"image": null
},
{
"name": "Mark Twain",
"actualQuote": "It is better to keep your mouth closed and let people think you are a fool than to open it and remove all doubt.",
"image": null
},
{
"name": "Mark Twain",
"actualQuote": "The secret of getting ahead is getting started.",
"image": null
},
{
"name": "Babe Ruth",
"actualQuote": "It’s hard to beat a person who never gives up.",
"image": null
}
]
},
{
"quoteTopic": "Motivational Quotes",
"topicImage": "motivational quotes",
"featured": true,
"QuotesList": [
{
"name": "Mark Twain",
"actualQuote": "Age is an issue of mind over matter. If you don't mind, it doesn't matter.",
"image": null
},
{
"name": "Mahatma Gandhi",
"actualQuote": "Learn as if you will live forever, live like you will die tomorrow.",
"image": null
},
{
"name": "Mary Kay Ash",
"actualQuote": "Don’t limit yourself. Many people limit themselves to what they think they can do. You can go as far as your mind lets you. What you believe, remember, you can achieve.",
"image": null
},
{
"name": "Unknown",
"actualQuote": "Hold the vision, trust the process.",
"image": null
}
]
},
{
"quoteTopic": "Success Quotes",
"topicImage": "success quotes",
"featured": false,
"QuotesList": [
{
"name": "Estee Lauder",
"actualQuote": "I never dreamed about success. I worked for it.",
"image": null
},
{
"name": "Thomas Edison",
"actualQuote": "Opportunity is missed by most people because it is dressed in overalls and looks like work.",
"image": null
},
{
"name": "Tom Lehrer",
"actualQuote": "Life is like a sewer… what you get out of it depends on what you put into it.",
"image": null
},
{
"name": "Walt Disney",
"actualQuote": "All our dreams can come true, if we have the courage to pursue them.",
"image": null
}
]
}
]
and here's the error I'm getting
Couldn't decode json, try again (to get the actual quote)!
keyNotFound(CodingKeys(stringValue: "name", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: "name", intValue: nil) ("name").", underlyingError: nil))
(NOTE: It RUNS/builds fine, but it just won't show the 'QuotesDetailView' page when I try to run it. It's SwiftUI.
Please let me know if I need to provide anymore information, thank you!
EDIT: here's how I decode my JSON
class DataService {
// Return an array of Quote Objects
static func getLocalData() -> [AllQuotes] {
// Begin the process of parsing the JSON File
// Get a URL path to json file
let pathString = Bundle.main.path(forResource: "quotes", ofType: "json")
// Check if pathString is nil, otherwise return empty Quotes List if it is.
guard pathString != nil else{
return [AllQuotes]()
}
// Create URL Object
let url = URL(fileURLWithPath: pathString!)
// Create Data Object
do {
let data = try Data(contentsOf: url)
// Parse the data
let decoder = JSONDecoder()
do {
let quoteData = try decoder.decode([AllQuotes].self, from: data)
// Set unique IDs for each instance
for newQuote in quoteData {
newQuote.id = UUID()
}
// Return the Quote
return quoteData
} catch {
// Couldn't decode json
print("Couldn't decode json, try again (to get the quotes TOPIC)!")
print(error)
}
} catch {
// Error fetching data from file
print("There was an error fetching the data from the file. - with the quote list!")
print(error)
}
// It didn't work, return an empty Quotes List
return [AllQuotes]()
}
// Return an array of ACTUAL Quotes Objects
static func getActualQuote() -> [Quotes] {
// Begin the process of parsing the JSON File
// Get a URL path to json file
let pathString = Bundle.main.path(forResource: "quotes", ofType: "json")
// Check if pathString is nil, otherwise return empty Quotes List if it is.
guard pathString != nil else{
return [Quotes]()
}
// Create URL Object
let url = URL(fileURLWithPath: pathString!)
// Create Data Object
do {
let data = try Data(contentsOf: url)
// Parse the data
let decoder = JSONDecoder()
do {
let actualQuoteData = try decoder.decode([Quotes].self, from: data)
// Set unique IDs for each instance
for actualQuote in actualQuoteData {
actualQuote.id = UUID()
}
// Return the Quote
return actualQuoteData
} catch {
// Couldn't decode json
print("Couldn't decode json, try again (to get the actual quote)!")
print(error)
}
} catch {
// Error fetching data from file
print("There was an error fetching the data from the file. - with the actual quote!")
print(error)
}
// It didn't work, return an empty Quotes List
return [Quotes]()
}
}

try this sample code, it shows how to decode your json data, and then display some info:
Since you don't show how you decode your json data, I'm gessing that
the error you get is due to decoding AllQuotes.self instead of [AllQuotes].self as required.
struct ContentView: View {
#State var quoteList = [Quotes]()
var body: some View {
List(quoteList) { quote in
Text(quote.name)
}
.onAppear {
let json = """
[
{
"quoteTopic": "Wise Quotes",
"topicImage": "wise quotes",
"featured": false,
"QuotesList": [
{
"name": "Lao Tzu",
"actualQuote": "The journey of a thousand miles begins with one step.",
"image": null
},
{
"name": "Mark Twain",
"actualQuote": "It is better to keep your mouth closed and let people think you are a fool than to open it and remove all doubt.",
"image": null
},
{
"name": "Mark Twain",
"actualQuote": "The secret of getting ahead is getting started.",
"image": null
},
{
"name": "Babe Ruth",
"actualQuote": "It’s hard to beat a person who never gives up.",
"image": null
}
]
},
{
"quoteTopic": "Motivational Quotes",
"topicImage": "motivational quotes",
"featured": true,
"QuotesList": [
{
"name": "Mark Twain",
"actualQuote": "Age is an issue of mind over matter. If you don't mind, it doesn't matter.",
"image": null
},
{
"name": "Mahatma Gandhi",
"actualQuote": "Learn as if you will live forever, live like you will die tomorrow.",
"image": null
},
{
"name": "Mary Kay Ash",
"actualQuote": "Don’t limit yourself. Many people limit themselves to what they think they can do. You can go as far as your mind lets you. What you believe, remember, you can achieve.",
"image": null
},
{
"name": "Unknown",
"actualQuote": "Hold the vision, trust the process.",
"image": null
}
]
},
{
"quoteTopic": "Success Quotes",
"topicImage": "success quotes",
"featured": false,
"QuotesList": [
{
"name": "Estee Lauder",
"actualQuote": "I never dreamed about success. I worked for it.",
"image": null
},
{
"name": "Thomas Edison",
"actualQuote": "Opportunity is missed by most people because it is dressed in overalls and looks like work.",
"image": null
},
{
"name": "Tom Lehrer",
"actualQuote": "Life is like a sewer… what you get out of it depends on what you put into it.",
"image": null
},
{
"name": "Walt Disney",
"actualQuote": "All our dreams can come true, if we have the courage to pursue them.",
"image": null
}
]
}
]
"""
if let data = json.data(using: .utf8) {
do {
let apiResponse = try JSONDecoder().decode([AllQuotes].self, from: data)
// print something
for quote in apiResponse {
print("---> quoteTopic: \(quote.quoteTopic)")
// all quotes
quoteList.append(contentsOf: quote.QuotesList)
}
} catch {
print("decode error: \(error)")
}
}
}
}
}
class AllQuotes: Identifiable, Decodable {
let id = UUID() // <-- here
var quoteTopic:String
var topicImage:String
var featured:Bool
var QuotesList:[Quotes]
// -- here
private enum CodingKeys: String, CodingKey {
// <-- here remove id
case quoteTopic, topicImage, featured, QuotesList
}
}
class Quotes: Identifiable, Decodable {
let id = UUID() // <-- here
var name:String
var actualQuote:String
var image:String?
// -- here
private enum CodingKeys: String, CodingKey {
// <-- here remove id
case name = "name"
case actualQuote = "actualQuote"
case image = "image"
}
}
EDIT-1: in view of the "new" code
struct ContentView: View {
#State var quoteList = [Quotes]()
var body: some View {
List(quoteList) { quote in
Text(quote.name)
}
.onAppear {
quoteList = DataService.getActualQuote()
print("---> quoteList: \(quoteList)")
}
}
}
class DataService {
// Return an array of Quote Objects
static func getLocalData() -> [AllQuotes] {
// Begin the process of parsing the JSON File
// Get a URL path to json file
let pathString = Bundle.main.path(forResource: "quotes", ofType: "json")
// Check if pathString is nil, otherwise return empty Quotes List if it is.
guard pathString != nil else{
return [AllQuotes]()
}
let url = URL(fileURLWithPath: pathString!)
do {
let data = try Data(contentsOf: url)
do {
let quoteData = try JSONDecoder().decode([AllQuotes].self, from: data)
return quoteData
} catch {
// Couldn't decode json
print("Couldn't decode json, try again (to get the quotes TOPIC)!")
print(error)
}
} catch {
// Error fetching data from file
print("There was an error fetching the data from the file. - with the quote list!")
print(error)
}
// It didn't work, return an empty Quotes List
return []
}
// Return an array of ACTUAL Quotes Objects
static func getActualQuote() -> [Quotes] {
// Begin the process of parsing the JSON File
// Get a URL path to json file
let pathString = Bundle.main.path(forResource: "quotes", ofType: "json")
// Check if pathString is nil, otherwise return empty Quotes List if it is.
guard pathString != nil else{
return [Quotes]()
}
// Create URL Object
let url = URL(fileURLWithPath: pathString!)
// Create Data Object
do {
let data = try Data(contentsOf: url)
do {
// -- here
let quoteData = try JSONDecoder().decode([AllQuotes].self, from: data)
// -- here
var actualQuoteData = [Quotes]()
for quote in quoteData {
actualQuoteData.append(contentsOf: quote.QuotesList)
}
// Return the Quotes
return actualQuoteData
} catch {
// Couldn't decode json
print("Couldn't decode json, try again (to get the actual quote)!")
print(error)
}
} catch {
// Error fetching data from file
print("There was an error fetching the data from the file. - with the actual quote!")
print(error)
}
// It didn't work, return an empty Quotes List
return []
}
}
EDIT-2: you can shorten your code, such as:
class DataService {
// Return an array of Quote Objects
static func getLocalData() -> [AllQuotes] {
if let pathString = Bundle.main.path(forResource: "quotes", ofType: "json") {
let url = URL(fileURLWithPath: pathString)
do {
let data = try Data(contentsOf: url)
let quoteData = try JSONDecoder().decode([AllQuotes].self, from: data)
return quoteData
} catch {
print(error)
}
}
return []
}
// Return an array of ACTUAL Quotes Objects
static func getActualQuote() -> [Quotes] {
var actualQuoteData = [Quotes]()
for quote in getLocalData() {
actualQuoteData.append(contentsOf: quote.QuotesList)
}
return actualQuoteData
}
}

Related

Swift The data couldn’t be read because it isn’t in the correct format

I am new to swift and trying to figure out how to parse JSON to a struct. I am trying to get an image from NASA Mar's Rover Photos.I am trying to follow tutorials online, but can't seem to fix this issue. What am I doing wrong here?
error:
Fatal error: The data couldn’t be read because it isn’t in the correct format.
import Foundation
class API {
class func getImage(_ onSucessus: #escaping ([LatestPhoto]) -> ()){
Constrant.session.dataTask(with: Constrant.request){(data, res, err) in
guard let data = data, err == nil else{
fatalError()
}
do{
let apod = try Constrant.decoder.decode([LatestPhoto].self, from: data)
DispatchQueue.main.async {
onSucessus(apod)
}
}
catch{
fatalError(error.localizedDescription)
}
}.resume()
}
}
Struct
struct LatestPhoto: Identifiable, Codable{
let id = UUID()
let imgSrc: String
let earthDate: String
enum CodingKeys: String, CodingKey {
case imgSrc = "img_src"
case earthDate = "earth_date"
}
}
JSON
{
"latest_photos": [
{
"id": 839114,
"sol": 3127,
"camera": {
"id": 20,
"name": "FHAZ",
"rover_id": 5,
"full_name": "Front Hazard Avoidance Camera"
},
"img_src": "https://mars.nasa.gov/msl-raw-images/proj/msl/redops/ods/surface/sol/03127/opgs/edr/fcam/FRB_675093431EDR_F0880366FHAZ00302M_.JPG",
"earth_date": "2021-05-23",
"rover": {
"id": 5,
"name": "Curiosity",
"landing_date": "2012-08-06",
"launch_date": "2011-11-26",
"status": "active"
}
},
{
"id": 839115,
"sol": 3127,
"camera": {
"id": 20,
"name": "FHAZ",
"rover_id": 5,
"full_name": "Front Hazard Avoidance Camera"
},
"img_src": "https://mars.nasa.gov/msl-raw-images/proj/msl/redops/ods/surface/sol/03127/opgs/edr/fcam/FLB_675093431EDR_F0880366FHAZ00302M_.JPG",
"earth_date": "2021-05-23",
"rover": {
"id": 5,
"name": "Curiosity",
"landing_date": "2012-08-06",
"launch_date": "2011-11-26",
"status": "active"
}
}
]
}
Your JSON format doesn't quite match what you're trying to decode. You need a wrapper for the latest_photos array at the root of your JSON object.
For example:
struct LatestPhotosWrapper: Codable {
let latestPhotos: [LatestPhoto]
enum CodingKeys: String, CodingKey {
case latestPhotos = "latest_photos"
}
}
let apod = try JSONDecoder().decode(LatestPhotosWrapper.self, from: data)
(Rather than providing a CodingKey, you can also look into the built-in systems for converting from snake case: https://developer.apple.com/documentation/foundation/jsondecoder/keydecodingstrategy/convertfromsnakecase)
Also, you may want to print the error and not just the error.localizedDescription -- you can get a better picture of what's going on. For example, with your original code, you get:
Expected to decode Array but found a dictionary instead.
Finally, you might check out app.quicktype.io -- you can paste in your JSON and get correct Swift structs pre-built for you.

No value associated with key CodingKeys with Unsplash API

Im trying to decode this json from the Unsplash API, but the ContentView is coming up as blank, and if I print the results then I am getting the "No value associated with key CodingKeys" error. Its strange, because I'm following this very new tutorial https://www.youtube.com/watch?v=CmOe9vNopjU. I am very puzzled, because this should be simple, but I am new to Swift.
here is the full error
"No value associated with key CodingKeys(stringValue: \"total\", intValue: nil) (\"total\").", underlyingError: nil))
here is the decoding request
class SearchObjectController : ObservableObject {
static let shared = SearchObjectController()
private init() {}
var token = "my client id"
#Published var results = [Result]()
#Published var searchText : String = "Forest"
func search () {
let url = URL(string: "https://api.unsplash.com/search/photos?query=\(searchText)")
var request = URLRequest(url: url!)
request.httpMethod = "GET"
request.setValue("Client-ID\(token)", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data else {return}
do {
let res = try JSONDecoder().decode(Results.self, from: data)
self.results.append(contentsOf: res.results)
print(self.results)
} catch {
print(error)
}
}
task.resume()
}
}
and these are the Structs i created for that request
struct Results : Codable {
var total : Int
var results : [Result]
}
struct Result : Codable {
var id : String
var description : String?
var urls : URLs
}
struct URLs : Codable {
var small : String
}
the json format for Unplash API Requests looks like this
{
"total": 133,
"total_pages": 7,
"results": [
{
"id": "eOLpJytrbsQ",
"created_at": "2014-11-18T14:35:36-05:00",
"width": 4000,
"height": 3000,
"color": "#A7A2A1",
"blur_hash": "LaLXMa9Fx[D%~q%MtQM|kDRjtRIU",
"likes": 286,
"liked_by_user": false,
"description": "A man drinking a coffee.",
"user": {
"id": "Ul0QVz12Goo",
"username": "ugmonk",
"name": "Jeff Sheldon",
"first_name": "Jeff",
"last_name": "Sheldon",
"instagram_username": "instantgrammer",
"twitter_username": "ugmonk",
"portfolio_url": "http://ugmonk.com/",
"profile_image": {
"small": "https://images.unsplash.com/profile-1441298803695-accd94000cac?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=32&w=32&s=7cfe3b93750cb0c93e2f7caec08b5a41",
"medium": "https://images.unsplash.com/profile-1441298803695-accd94000cac?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=64&w=64&s=5a9dc749c43ce5bd60870b129a40902f",
"large": "https://images.unsplash.com/profile-1441298803695-accd94000cac?ixlib=rb-0.3.5&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=128&w=128&s=32085a077889586df88bfbe406692202"
},
"links": {
"self": "https://api.unsplash.com/users/ugmonk",
"html": "http://unsplash.com/#ugmonk",
"photos": "https://api.unsplash.com/users/ugmonk/photos",
"likes": "https://api.unsplash.com/users/ugmonk/likes"
}
},
"current_user_collections": [],
"urls": {
"raw": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f",
"full": "https://hd.unsplash.com/photo-1416339306562-f3d12fefd36f",
"regular": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&s=92f3e02f63678acc8416d044e189f515",
"small": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&s=263af33585f9d32af39d165b000845eb",
"thumb": "https://images.unsplash.com/photo-1416339306562-f3d12fefd36f?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&s=8aae34cf35df31a592f0bef16e6342ef"
},
"links": {
"self": "https://api.unsplash.com/photos/eOLpJytrbsQ",
"html": "http://unsplash.com/photos/eOLpJytrbsQ",
"download": "http://unsplash.com/photos/eOLpJytrbsQ/download"
}
},
// more photos ...
]
}
It's a common practice for a lot of APIs to return a detailed description of the error in the response body together with the error code when the request can't be processed. Seems that it's your case since the JSON parsing fails on the first field of the structure. Check the error and response.statusCode in the dataTask's completion block first to be sure that the API has successfully processed your request and returned valid data.
It was a missing a space between Client-ID and (token) that was causing the error.

How to parse array of objects of json with SwiftUI

completely new to Swift here, so I have no idea how to even use print debugging, so thought I would ask here.
I am trying to parse a series of objects, each one of them in this format:
{
"id": 0,
"title": "Example Title",
"targets": [
{
"name": "Example Name"
},
{
"name": "Example Name"
},
{
"name": "Example Name"
},
{
"name": "Example Name"
}
],
"benefits": [
{
"name": "Example Benefit"
},
{
"name": "Example Benefit"
},
{
"name": "Example Benefit"
}
],
"steps": [
{
"name": "Example Step"
},
{
"name": "Example Step"
}
],
"videoURL": "https://someurl.com"
},
So I have a struct defined as such
struct Obj: Codable, Hashable {
var id:Int
var title:String
var targets:[String]
var benefits:[String]
var steps:[String]
var videoURL:String
}
And using
let objs:[Obj] = decode([Obj].self, from: "./Data/Objs.json")
Where decode is this function
func decode<T: Decodable>(_ type:T.Type, from filename:String) -> T {
guard let json = Bundle.main.url(forResource: filename, withExtension: nil) else {
fatalError("Failed to locate \(filename) in app bundle.")
}
guard let jsonData = try? Data(contentsOf: json) else {
fatalError("Failed to load \(filename) from app bundle.")
}
let decoder = JSONDecoder()
guard let result = try? decoder.decode(T.self, from: jsonData) else {
fatalError("Failed to decode \(filename) from app bundle.")
}
return result
}
However when accessing the data in Objs, I get an error in the SwiftUI preview objs.app may have crashed. Check ... for any crash logs in your application which leads me to believe I am using JSONDecoder() incorrectly. Any help is appreciated!
So the problem here is how you are decoding inner content of the targets, steps and benifits.
Targets/Steps/Benifit contains array of object but in the Codable structure of yours, you have given it as a array of strings [String]. You need to correct that and Check.
Create one new structure:
struct Name : Codable {
var name : String
}
Your final object will look like:
struct Obj: Codable, Hashable {
var id:Int
var title:String
var targets:[Name]
var benefits:[Name]
var steps:[Name]
var videoURL:String
}
The key thing you should remember is that at the time of parsing nested object you will have to create another structure with codable conformance.

Am I converting JSON data to a Swift variable the long way?

I am reading json data from a file and trying to move it into a NSDictionary and I am wondering if there is a more concise way to do it. The code shown below works fine. In my program the Astruct-type variable has more than 25 Bstruct-type variables. I have several files similar to the one I show. So it leads to a lot of cumbersome programming.
import UIKit
struct Bstruct {
var label = String()
var inputTypeStr = String()
var list = [String]()
}
struct Astruct {
// in real situation this has a over 25 variables
// limited to 3 for this question
var number = Bstruct()
var customer = Bstruct()
var location = Bstruct()
}
func loadJson(forFilename fileName: String) -> NSDictionary? {
if let url = Bundle.main.url(forResource: fileName, withExtension: "json") {
if let data = NSData(contentsOf: url) {
do {
let dictionary = try JSONSerialization.jsonObject(with: data as Data, options: .allowFragments) as? NSDictionary
return dictionary
} catch {
print("Error!! Unable to parse \(fileName).json")
}
}
print("Error!! Unable to load \(fileName).json")
}
return nil
}
func fillAstruct (value: NSDictionary) -> Bstruct {
return Bstruct(label: value["label"] as! String, inputTypeStr: value["inputTypeStr"] as! String, list: value["list"] as! [String])
}
var aVar = Astruct()
let json = loadJson(forFilename: "document")! as NSDictionary
let d = json["aTemplate"]! as! NSDictionary
print("d = \(d)")
// load d into aVar, appears to be complex particularly if the variable has a large number of variables in aVar and the json file
for d1 in d {
let key = String(describing: d1.0)
let value = d1.1 as! NSDictionary
switch key {
case "number":
aVar.number = fillAstruct(value: value)
case "customer":
aVar.customer = fillAstruct(value: value)
case "location":
aVar.location = fillAstruct(value: value)
default: break
}
}
print("\(aVar)")
The JSON file is shown below:
{
"aTemplate": {
"number": {
"label": "Number",
"inputTypeStr": "selection",
"list": [
"A",
"B",
"C"
]
},
"customer": {
"label": "Customer",
"inputTypeStr": "label",
"list": [
""
]
},
"location": {
"label": "location",
"inputTypeStr": "label",
"list": [
""
]
}
}
}

Parsing JSON response in Swift 3

I've got an API endpoint that returns JSON in the following format:
[
{
"id": "1",
"name": "John"
},
{
"id": "2",
"name": "Jane"
},
{
"id": "3",
"name": "Nick"
}
]
I am trying to parse this in Swift 3, but I can only find examples to parse JSON formatted like so:
{
"blogs": [
{
"needspassword": true,
"id": 73,
"url": "http://remote.bloxus.com/",
"name": "Bloxus test"
},
{
"needspassword": false,
"id": 74,
"url": "http://flickrtest1.userland.com/",
"name": "Manila Test"
}
],
"stat": "ok"
}
, which has an extra level above what mine does.
So, where examples I've seen are simply parsing their data like jsonResponse["blogs"], I can't do that as my format is different.
How can I parse the format I've got, or how can I return a format that is easier to parse?
Any suggestions appreciated, thanks!
You can just do the following :
let data = // Data received from WS
do {
let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions()) as? [[String : String]]
//json is now an array from dictionary matching your model
}
catch {
//handle error
}
This will parse it when placed in the network call.
do {
let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions()) as! [[String : AnyObject]]
let firstPerson = json[0]
print(firstPerson)
let id = firstPerson["id"] as! String
print(id)
let name = firstPerson["name"] as! String
print(name)
} catch {
//handle error
}
Also, I tend to be against advising third party libraries, but SwiftyJSON is an exception I make. If you want to try it, add this to your pod file:
pod SwiftyJSON', '3.0.0'
Documentation: https://github.com/SwiftyJSON/SwiftyJSON
EDIT - Answering Comment:
Replacement line:
if let id = firstPerson["id"] as? String {
print(id)
}
Replacement line (if you need to hold on to the value):
var thisId: String?
if let id = firstPerson["id"] as? String {
thisId = id
}
print(thisId ?? "")
i don't really know swift but there might be the equivalent of ajax json encoding (server side you json_encode your array and client side you json_decode the response)
the idea is to have the same formatter that encodes and decodes the data