Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 407
masterqp Avatar asked Aug 29 '17 19:08

masterqp


People also ask

How do I decode a JSON array in Swift?

First we spin up a _JSONDecoder, the private class that conforms to Decoder and contains JSON-specific logic. Remember T is the generic parameter for the Swift equivalent to topLevel; in this case, it’s [Int] aka Array<Int> so we can decode our array [0, 1, 2].

How does the Swift decoding process work?

As you might expect, the overall decoding process works like the reverse of the encoding process: Dispatch to each type’s Decodable initializer to reconstruct a series of Swift instances Let’s start with a JSON string representing an array of integers and turn that into some Data:

What is the difference between JSONserialization and jsondecoder?

Note that the decode () method needs to know the type of the result instance. In contrast to JSONSerialization which understands JSON types such as strings and numbers and arrays and dictionaries, JSONDecoder instantiates anything that’s Decodable — that’s how you can decode JSON directly to your own types.

How many Unbox () functions are there in a JSON decoder?

One price to pay is lots of repeated code in decoders; if you look at the rest of JSONEncoder.swift, you’ll find 18 unbox () functions to cover all the integer types, floats, strings, dates, etc. What would the simplest custom encoder and decoder look like?


1 Answers

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).

like image 77
nathan Avatar answered Oct 16 '22 15:10

nathan