0

I am trying to create some structs to decode some JSON received from an API using JSONSerialization.jsonObject(with: data, options: [])

This is what the JSON looks like:

{"books":[{"title":"The Fountainhead.","author":"Ayn Ranyd"},{"title":"Tom Sawyer","author":"Mark Twain"},{"title":"Warhol","author":"Blake Gopnik"}]}

Here are the structs that I am trying to use for decoding.

struct BooksReturned : Codable {
        let books : [Book]?
    }
    struct Book : Codable {
        let BookParts: Array<Any>?
    }
    struct BookParts : Codable {
        let titleDict : Dictionary<String>?
        let authorDict : Dictionary<String>?
    }

The error is:

The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.})))

The non-working code I am using to decode is:

let task = session.dataTask(with: url) { data, response, error in
            if let data = data, error == nil {
                let nsdata = NSData(data: data)
                DispatchQueue.main.async {
                    if let str = String(data: data, encoding: .utf8) {

                        let json = try? JSONSerialization.jsonObject(with: data, options: [])                        
                        do {

                            let mybooks = try JSONDecoder().decode(BooksReturned.self, from: data)
                             //do something with book
                            }

                        } catch {
                            print(error.localizedDescription)
                            print(error)
                        }
                    }
                }
            } else {
                // Failure
            }
        }
        task.resume()
    }

I have some very limited ability to change JSON. The only thing I can do is remove the "books" : Everything else is received from an external API.

Thanks for any suggestions on how to get this to work.

3
  • The error is saying that you have invalid JSON. Could you print let res = data.map { String(format: "02hhX", $0) }.joined()? Commented Jun 10, 2020 at 16:45
  • Good while you are learning the ropes. But when you have lots of json to parse and create models I prefer tools like - app.quicktype.io Its a fast way to create models, does all the checks for you, and creates models in couple different languages. Try it out once. Commented Jun 10, 2020 at 17:03
  • Wow, just tried app.quicktype.io. Awesome. Commented Jun 10, 2020 at 19:00

1 Answer 1

1

The JSON you provided seems to be valid. Modify your Book model and the decoding part as the following.

Model:

struct Book: Codable {
    let title, author: String
}

Decoding:

let task = session.dataTask(with: url) { data, response, error in
    if let data = data, error == nil {
        DispatchQueue.main.async {
            do {
                let mybooks = try JSONDecoder().decode(BooksReturned.self, from: data)
                print(mybooks)
            }
        } catch {
            print(error.localizedDescription)
            print(error)
        }
    }
} else {
    // Failure
}
task.resume()
Sign up to request clarification or add additional context in comments.

4 Comments

am I keeping the BooksReturned struct and getting rid of the BookParts so I have BooksReturned and the new code for Book?
Get rid of the BookParts and keep the BookReturned as given above we're trying to decode BookReturned.
Follow up question. I was under the impression that [Books] would give me an array of books but when I try to call BooksReturned[0] I get error that Type BooksRetuned has no subscript Members. How would I get first item?
I was finally able to reference this with let abook = mybooks?.books?[0] . I guess the actual array is books, not BooksReturned

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.