No value associated with key CodingKeys with Unsplash API - json

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.

Related

JSON parsing error - No value associated with key CodingKeys

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
}
}

Decoding Json in swift - Array but now a dictionary

I previously decoded the following response correctly:
GET https://api.spoonacular.com/recipes/findByNutrients?minCarbs=10&maxCarbs=50&number=2
[
{
"calories": 210,
"carbs": "43g",
"fat": "3g",
"id": 90629,
"image": "https://spoonacular.com/recipeImages/90629-312x231.jpg",
"imageType": "jpg",
"protein": "1g",
"title": "Baked Apples in White Wine"
},
{
"calories": 226,
"carbs": "33g",
"fat": "10g",
"id": 284420,
"image": "https://spoonacular.com/recipeImages/284420-312x231.jpg",
"imageType": "jpg",
"protein": "2g",
"title": "Chocolate Silk Pie with Marshmallow Meringue"
}
]
Using this codable model:
struct RecipieAPI: Codable {
var calories : Int
var carbs : String
var fat : String
var id : Int
var image : String
var imageType : String
var protein : String
var title: String
}
However I am now using a different api endpoint with the following response:
GET https://api.spoonacular.com/recipes/complexSearch?query=pasta&maxFat=25&number=2
{
"offset": 0,
"number": 2,
"results": [
{
"id": 716429,
"calories": 584,
"carbs": "84g",
"fat": "20g",
"image": "https://spoonacular.com/recipeImages/716429-312x231.jpg",
"imageType": "jpg",
"protein": "19g",
"title": "Pasta with Garlic, Scallions, Cauliflower & Breadcrumbs"
},
{
"id": 715538,
"calories": 521,
"carbs": "69g",
"fat": "10g",
"image": "https://spoonacular.com/recipeImages/715538-312x231.jpg",
"imageType": "jpg",
"protein": "35g",
"title": "What to make for dinner tonight?? Bruschetta Style Pork & Pasta"
}
],
"totalResults": 86
}
And I am very unsure how I should change my code to get the array inside the dictionary appropriately. Any help would be really really appreciated :)
Note this is in my services class:
AF.request("https://api.spoonacular.com/recipes/complexSearch?apiKey=\(NetworkServices.apiKey)&diet=Whole30&minCarbs=\(minCarbs)&maxCarbs=\(maxCarbs)&number=\(number)", method: .get).responseJSON { (response) in
switch response.result {
case .success(_):
let decoder = JSONDecoder()
if let data = response.data {
do {
let nutrients = try decoder.decode([RecipieAPI].self, from: data)
completionHandler(nutrients, nil)
} catch let error {
completionHandler(nil, error)
}
}
case .failure(let error):
completionHandler(nil, error)
}
}
Link to documentation of api endpoints - sroll to bottom of page to see examples:
https://spoonacular.com/food-api/docs#Search-Recipes-by-Nutrients
https://spoonacular.com/food-api/docs#Search-Recipes-Complex
Add the new root model with the nested key results which you were decoding previously
struct Root: Codable {
var results : [RecipieAPI]
}
struct RecipieAPI: Codable {
var calories : Int?
var carbs : String
var fat : String
var id : Int
var image : String
var imageType : String
var protein : String
var title: String
}
Then
let nutrients = try decoder.decode(Root.self, from: data)
completionHandler(nutrients.results, nil)

JSON Formatter to Swift Struct to Parsing

I'm at a loss right now of how to properly convert my JSON file to Swift Struct then parse it accordingly. I cant seem to parse the retrieved data. When running a print statement in the do-try-catch block of my JSONDecoder, it catches an error during parsing.
My questions are:
Did I format my Structs correctly?
Am I missing something in my method?
See below for details...
Appreciate the help!
Here's a snippet of my JSON
{
"data": [
{
"day": 1,
"image": {
"attribution": "© YouVersion",
"url": "//imageproxy-cdn.youversionapi.com/{width}x{height},png/https://s3.amazonaws.com/static-youversionapi-com/images/base/10778/1280x1280.jpg"
},
"verse": {
"human_reference": "Proverbs 16:9",
"html": null,
"text": "A man’s heart plans his course, but Yahweh directs his steps.",
"url": "https://www.bible.com/bible/206/PRO.16.9",
"usfms": [
"PRO.16.9"
]
}
},
{
"day": 2,
"image": {
"attribution": "© YouVersion",
"url": "//imageproxy-cdn.youversionapi.com/{width}x{height},png/https://s3.amazonaws.com/static-youversionapi-com/images/base/27119/1280x1280.jpg"
},
"verse": {
"human_reference": "Psalms 90:12",
"html": null,
"text": "So teach us to count our days, that we may gain a heart of wisdom.",
"url": "https://www.bible.com/bible/206/PSA.90.12",
"usfms": [
"PSA.90.12"
]
}
},
{
"day": 3,
"image": {
"attribution": "© YouVersion",
"url": "//imageproxy-cdn.youversionapi.com/{width}x{height},png/https://s3.amazonaws.com/static-youversionapi-com/images/base/27117/1280x1280.jpg"
},
"verse": {
"human_reference": "Proverbs 16:3",
"html": null,
"text": "Commit your deeds to Yahweh, and your plans shall succeed.",
"url": "https://www.bible.com/bible/206/PRO.16.3",
"usfms": [
"PRO.16.3"
]
}
]
}
Here's my resulting Struct(s)
struct VerseData: Codable {
var data: [Datum]
}
struct Datum: Codable {
let day: Int
let image: VerseImageData
let verse: VerseDetails
}
struct VerseImageData: Codable {
var attribution: String?
var url: String = ""
}
struct VerseDetails: Codable {
var humanReference: String = ""
var url: String = ""
var text: String = ""
}
Here's my call in my VC.Swift
func getData() {
let urlStr = URL(string: "https://developers.youversionapi.com/1.0/verse_of_the_day?version_id=206")
let request = NSMutableURLRequest(url: urlStr!)
request.setValue("myAPIKey", forHTTPHeaderField: "X-YouVersion-Developer-Token")
request.addValue("en", forHTTPHeaderField: "Accept-Language")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.httpMethod = "GET"
print(request)
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest) { (data, response, error) in
guard let data = data else { return }
do {
let verseData = try JSONDecoder().decode(VerseData.self, from: data)
print(verseData)
} catch {
print("error")
}
}
dataTask.resume()
}
}
Try to print error
"humanReference"? should be "human_reference" according to the JSON and API documentation

Swift 4 json decoder error flickr

I am trying out the new JSONDecoder() in swift 4 and am trying to parse the following flickr API response : (https://api.flickr.com/services/rest/?api_key=api_key&method=flickr.photos.search&format=json&per_page=25&text=hello&nojsoncallback=1). However I get an error saying that "error processing json data: The data couldn’t be read because it isn’t in the correct format." However the data seems to be in the correct format to me. Am I doing anything wrong?
let dataTask = session.dataTask(with: urlRequest) { (data, response, error) in
if let error = error {
print("json error: \(error.localizedDescription)")
return
} else if let data = data {
print(response)
do {
let decoder = JSONDecoder()
print(data)
let flickrPhotos = try decoder.decode(FlickrImageResult.self, from: data)
} catch {
dump(data)
print("json error: \(error.localizedDescription)")
}
}
}
dataTask.resume()
My data models are
struct FlickrImageResult : Codable {
var photos : FlickrPhoto? = nil
}
struct FlickrPhoto : Codable {
var photo : [FlickrURLs]? = nil
}
struct FlickrURLs: Codable {
var id : String? = nil
var owner: String? = nil
var secret: String? = nil
var server: String? = nil
var farm: String? = nil
}
I changed the number of images requested to 2 and Printing out the data returns
Optional({"photos":{"page":1,"pages":120197,"perpage":2,"total":"240393","photo":[{"id":"36729752762","owner":"152440263#N02","secret":"e62ba3e18b","server":"4432","farm":5,"title":"Hello there","ispublic":1,"isfriend":0,"isfamily":0},{"id":"36729384952","owner":"141041947#N06","secret":"bc0e5af630","server":"4380","farm":5,"title":"POST\ud83d\udd25 #891 | Hello Tuesday | Krescendo","ispublic":1,"isfriend":0,"isfamily":0}]},"stat":"ok"})
The only problem with your model is that farm is actually an Int. Here's a more complete version of your model accoirding to the docs (https://www.flickr.com/services/api/flickr.photos.search.html):
struct FlickrImageResult: Codable {
let photos : FlickrPagedImageResult?
let stat: String
}
struct FlickrPagedImageResult: Codable {
let photo : [FlickrURLs]
let page: Int
let pages: Int
let perpage: Int
let total: String
}
struct FlickrURLs: Codable {
let id : String
let owner: String
let secret: String
let server: String
let farm: Int
// let title: String
// If needed, camel-case and use CodingKeys enum
//let ispublic: Int
//let isfriend: Int
//let isfamily: Int
}
let jsonData = """
{
"photos": {
"page": 1,
"pages": 13651,
"perpage": 25,
"total": "341263",
"photo": [
{
"id": "36499638920",
"owner": "55126206#N07",
"secret": "7e82dee0ba",
"server": "4346",
"farm": 5,
"title": "[BREATHE]-Ririko,Sayaka&Chiyoko",
"ispublic": 1,
"isfriend": 0,
"isfamily": 0
},
{
"id": "36724435032",
"owner": "92807782#N04",
"secret": "6d830d4a75",
"server": "4354",
"farm": 5,
"title": "Serendipity Designs # SWANK August 2017",
"ispublic": 1,
"isfriend": 0,
"isfamily": 0
},
{
"id": "36087089863",
"owner": "152685136#N08",
"secret": "a4a3f2fe0a",
"server": "4365",
"farm": 5,
"title": "Hello Kitty Scooter",
"ispublic": 1,
"isfriend": 0,
"isfamily": 0
},
{
"id": "36086949593",
"owner": "151818203#N02",
"secret": "fc1207d373",
"server": "4334",
"farm": 5,
"title": "Hip, Hip! It's Chip!",
"ispublic": 1,
"isfriend": 0,
"isfamily": 0
},
{
"id": "36498504410",
"owner": "148300038#N02",
"secret": "5c7f6ff3e1",
"server": "4391",
"farm": 5,
"title": "Hello Kotti",
"ispublic": 1,
"isfriend": 0,
"isfamily": 0
}
]
},
"stat": "ok"
}
""".data(using: .utf8)!
let flickrPhotos = try! JSONDecoder().decode(FlickrImageResult.self, from: jsonData)
print(flickrPhotos)
P.S: The message error processing json data: The data couldn’t be read because it isn’t in the correct format. is the localized error message, use print(error) instead of print(errorlocalizedDescription) to obtain all the error data available (in your case, it will print that there's an issue when trying to decode the farm key).

Accessing JSON data in swift

I am trying to access JSON data in my swift code and I'm having trouble getting it to return correctly. Here is my JSON code:
[
{
"id": "1",
"isImage": "0",
"name": "test name",
"post": "test post",
"time": "10:27",
"ip": "192.168.1.1",
"city ": "Columbus",
"latlong": "39.896418,-82.9751105",
"clientID": "clientID",
"popularity": "300"
},
{
"id": "2",
"isImage": "0",
"name": "test name two",
"post": "test post two",
"time": "13:37",
"ip": "192.168.1.1",
"city ": "Columbus",
"latlong": "39.896418,-82.9751105",
"clientID": "clientID",
"popularity": "69"
}
]
I'd just like to know how to access the data by their keys json[0].['id'] or?
I am currently using this json.swift module and trying to access the data with
func jsonHandle(data: NSString) {
var parsedJSON = JSON(data)
var id = parsedJSON[0].["id"]
NSLog("\(id)")
}
but it returns nothing. Any Ideas?
You can call the JSON(string:...) rendition and eliminate the period between the [0] and the ["id"]:
func jsonHandle(data: NSString) {
let parsedJSON = JSON(string: data)
var id = parsedJSON[0]["id"]
NSLog("\(id)")
}
Or, if you had a NSData you could use the JSON(data: ...) rendition:
func jsonHandle(data: NSData) {
let parsedJSON = JSON(data: data)
let id = parsedJSON[0]["id"]
NSLog("\(id)")
}
Or, if you wanted to use the native NSJSONSerialization, rather than that third-party library, you could:
func jsonHandle(data: NSData) {
var error: NSError?
let parsedJSON = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &error) as NSArray
let id = parsedJSON[0]["id"]
NSLog("\(id)")
}
Personally, I'd lean towards the standard NSJSONSerialization approach as it's a tried and true approach, but that's your call.