Marvel API Swift4 JSON Decoding
up vote
0
down vote
favorite
I'm making a basic IOS app, based on the "App development with Swift" book from Apple. My app uses the Marvel API. I'm trying to reach the name and the description of the heroes.
The connection with the API works completely and has been tested multiple times. The problem hasn't anything do to with this.
My problem is the fact that the JSON result is 3 times nested, I have no idea how to reach this in Swift 4.
Here is an example of the JSON result of 1 hero. All Heroes can be found in the "result"
The JSON structure can be found here
My code has a fatal error:
Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "results", intValue: nil)
let jsonDecoder = JSONDecoder()
let task = URLSession.shared.dataTask(with: url) { (data,
response, error) in
try! jsonDecoder.decode(CharactersContainer.self,
from: data!) //error here
if let data = data,
let char = try? jsonDecoder.decode(CharactersContainer.self, from: data) {
print(char.characters)
print("succes")
} else {
print("failed")
}
}
Now here are my models:
import Foundation
struct Character: Codable {
var name: String
var description: String
//var url: Image
enum CodingKeys: String, CodingKey {
case name
case description
//case url = "thumbnail"
}
init(from decoder: Decoder) throws {
let valueContainer = try decoder.container(keyedBy: CharactersContainer.CodingKeys.self).nestedContainer(keyedBy: Characters.CodingKeys.self, forKey: .characters).nestedContainer(keyedBy: Character.CodingKeys.self, forKey: .characters)
if let name = try valueContainer.decodeIfPresent(String.self, forKey: CodingKeys.name) {
self.name = name
} else {
self.name = ""
}
if let description = try valueContainer.decodeIfPresent(String.self, forKey: CodingKeys.description) {
self.description = description
} else {
self.description = ""
}
// self.url = try valueContainer.decode(URL.self, forKey: CodingKeys.url)
}
}
struct Characters : Decodable{
var characters : [Character]
enum CodingKeys: String, CodingKey {
case characters = "data"
}
}
struct CharactersContainer : Decodable {
var characters : Characters
//var total: Int
enum CodingKeys: String, CodingKey {
case characters = "results"
//case total
}
}
I have no idea what I did wrong, since I saw some examples who did the exact same thing.
Thanks for checking in!
json swift api nested decode
add a comment |
up vote
0
down vote
favorite
I'm making a basic IOS app, based on the "App development with Swift" book from Apple. My app uses the Marvel API. I'm trying to reach the name and the description of the heroes.
The connection with the API works completely and has been tested multiple times. The problem hasn't anything do to with this.
My problem is the fact that the JSON result is 3 times nested, I have no idea how to reach this in Swift 4.
Here is an example of the JSON result of 1 hero. All Heroes can be found in the "result"
The JSON structure can be found here
My code has a fatal error:
Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "results", intValue: nil)
let jsonDecoder = JSONDecoder()
let task = URLSession.shared.dataTask(with: url) { (data,
response, error) in
try! jsonDecoder.decode(CharactersContainer.self,
from: data!) //error here
if let data = data,
let char = try? jsonDecoder.decode(CharactersContainer.self, from: data) {
print(char.characters)
print("succes")
} else {
print("failed")
}
}
Now here are my models:
import Foundation
struct Character: Codable {
var name: String
var description: String
//var url: Image
enum CodingKeys: String, CodingKey {
case name
case description
//case url = "thumbnail"
}
init(from decoder: Decoder) throws {
let valueContainer = try decoder.container(keyedBy: CharactersContainer.CodingKeys.self).nestedContainer(keyedBy: Characters.CodingKeys.self, forKey: .characters).nestedContainer(keyedBy: Character.CodingKeys.self, forKey: .characters)
if let name = try valueContainer.decodeIfPresent(String.self, forKey: CodingKeys.name) {
self.name = name
} else {
self.name = ""
}
if let description = try valueContainer.decodeIfPresent(String.self, forKey: CodingKeys.description) {
self.description = description
} else {
self.description = ""
}
// self.url = try valueContainer.decode(URL.self, forKey: CodingKeys.url)
}
}
struct Characters : Decodable{
var characters : [Character]
enum CodingKeys: String, CodingKey {
case characters = "data"
}
}
struct CharactersContainer : Decodable {
var characters : Characters
//var total: Int
enum CodingKeys: String, CodingKey {
case characters = "results"
//case total
}
}
I have no idea what I did wrong, since I saw some examples who did the exact same thing.
Thanks for checking in!
json swift api nested decode
Basically don'ttry!
while developing JSON parsing withCodable
. Add ado - catch
block and print theerror
instance. It might contain more information than the fatal error. And mapping keys to the same property name (characters
) in different structs can be confusing
– vadian
Nov 22 at 17:11
Valid criticism. I changed the names of the classes to MarvelData and Result
– ConnorM
Nov 22 at 17:43
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I'm making a basic IOS app, based on the "App development with Swift" book from Apple. My app uses the Marvel API. I'm trying to reach the name and the description of the heroes.
The connection with the API works completely and has been tested multiple times. The problem hasn't anything do to with this.
My problem is the fact that the JSON result is 3 times nested, I have no idea how to reach this in Swift 4.
Here is an example of the JSON result of 1 hero. All Heroes can be found in the "result"
The JSON structure can be found here
My code has a fatal error:
Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "results", intValue: nil)
let jsonDecoder = JSONDecoder()
let task = URLSession.shared.dataTask(with: url) { (data,
response, error) in
try! jsonDecoder.decode(CharactersContainer.self,
from: data!) //error here
if let data = data,
let char = try? jsonDecoder.decode(CharactersContainer.self, from: data) {
print(char.characters)
print("succes")
} else {
print("failed")
}
}
Now here are my models:
import Foundation
struct Character: Codable {
var name: String
var description: String
//var url: Image
enum CodingKeys: String, CodingKey {
case name
case description
//case url = "thumbnail"
}
init(from decoder: Decoder) throws {
let valueContainer = try decoder.container(keyedBy: CharactersContainer.CodingKeys.self).nestedContainer(keyedBy: Characters.CodingKeys.self, forKey: .characters).nestedContainer(keyedBy: Character.CodingKeys.self, forKey: .characters)
if let name = try valueContainer.decodeIfPresent(String.self, forKey: CodingKeys.name) {
self.name = name
} else {
self.name = ""
}
if let description = try valueContainer.decodeIfPresent(String.self, forKey: CodingKeys.description) {
self.description = description
} else {
self.description = ""
}
// self.url = try valueContainer.decode(URL.self, forKey: CodingKeys.url)
}
}
struct Characters : Decodable{
var characters : [Character]
enum CodingKeys: String, CodingKey {
case characters = "data"
}
}
struct CharactersContainer : Decodable {
var characters : Characters
//var total: Int
enum CodingKeys: String, CodingKey {
case characters = "results"
//case total
}
}
I have no idea what I did wrong, since I saw some examples who did the exact same thing.
Thanks for checking in!
json swift api nested decode
I'm making a basic IOS app, based on the "App development with Swift" book from Apple. My app uses the Marvel API. I'm trying to reach the name and the description of the heroes.
The connection with the API works completely and has been tested multiple times. The problem hasn't anything do to with this.
My problem is the fact that the JSON result is 3 times nested, I have no idea how to reach this in Swift 4.
Here is an example of the JSON result of 1 hero. All Heroes can be found in the "result"
The JSON structure can be found here
My code has a fatal error:
Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "results", intValue: nil)
let jsonDecoder = JSONDecoder()
let task = URLSession.shared.dataTask(with: url) { (data,
response, error) in
try! jsonDecoder.decode(CharactersContainer.self,
from: data!) //error here
if let data = data,
let char = try? jsonDecoder.decode(CharactersContainer.self, from: data) {
print(char.characters)
print("succes")
} else {
print("failed")
}
}
Now here are my models:
import Foundation
struct Character: Codable {
var name: String
var description: String
//var url: Image
enum CodingKeys: String, CodingKey {
case name
case description
//case url = "thumbnail"
}
init(from decoder: Decoder) throws {
let valueContainer = try decoder.container(keyedBy: CharactersContainer.CodingKeys.self).nestedContainer(keyedBy: Characters.CodingKeys.self, forKey: .characters).nestedContainer(keyedBy: Character.CodingKeys.self, forKey: .characters)
if let name = try valueContainer.decodeIfPresent(String.self, forKey: CodingKeys.name) {
self.name = name
} else {
self.name = ""
}
if let description = try valueContainer.decodeIfPresent(String.self, forKey: CodingKeys.description) {
self.description = description
} else {
self.description = ""
}
// self.url = try valueContainer.decode(URL.self, forKey: CodingKeys.url)
}
}
struct Characters : Decodable{
var characters : [Character]
enum CodingKeys: String, CodingKey {
case characters = "data"
}
}
struct CharactersContainer : Decodable {
var characters : Characters
//var total: Int
enum CodingKeys: String, CodingKey {
case characters = "results"
//case total
}
}
I have no idea what I did wrong, since I saw some examples who did the exact same thing.
Thanks for checking in!
json swift api nested decode
json swift api nested decode
edited Nov 22 at 16:57
Craig Siemens
9,11111839
9,11111839
asked Nov 22 at 16:55
ConnorM
1
1
Basically don'ttry!
while developing JSON parsing withCodable
. Add ado - catch
block and print theerror
instance. It might contain more information than the fatal error. And mapping keys to the same property name (characters
) in different structs can be confusing
– vadian
Nov 22 at 17:11
Valid criticism. I changed the names of the classes to MarvelData and Result
– ConnorM
Nov 22 at 17:43
add a comment |
Basically don'ttry!
while developing JSON parsing withCodable
. Add ado - catch
block and print theerror
instance. It might contain more information than the fatal error. And mapping keys to the same property name (characters
) in different structs can be confusing
– vadian
Nov 22 at 17:11
Valid criticism. I changed the names of the classes to MarvelData and Result
– ConnorM
Nov 22 at 17:43
Basically don't
try!
while developing JSON parsing with Codable
. Add a do - catch
block and print the error
instance. It might contain more information than the fatal error. And mapping keys to the same property name (characters
) in different structs can be confusing– vadian
Nov 22 at 17:11
Basically don't
try!
while developing JSON parsing with Codable
. Add a do - catch
block and print the error
instance. It might contain more information than the fatal error. And mapping keys to the same property name (characters
) in different structs can be confusing– vadian
Nov 22 at 17:11
Valid criticism. I changed the names of the classes to MarvelData and Result
– ConnorM
Nov 22 at 17:43
Valid criticism. I changed the names of the classes to MarvelData and Result
– ConnorM
Nov 22 at 17:43
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
In the JSON, data
contains the results
key. The way your keys are set up, it's expecting results
to contain a data
key.
CharactersContainer.CodingKeys.characters
should probably be "data"
Characters.CodingKeys.characters
should probably be "results"
Edit:
There's another issue in Character
. It is trying to get a contain keyed by CharactersContainer.CodingKeys.self
but it should probably be Character.CodingKeys.self
You're right, but if u change it. I still get an error saying: Thread 5: Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "data", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), CodingKeys(stringValue: "results", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "Cannot get KeyedDecodingContainer<CodingKeys> -- no value found for key CodingKeys(stringValue: "data", intValue: nil) ("data")", underlyingError: nil))
– ConnorM
Nov 22 at 17:09
Can you convertdata
to a string and print it out before you try decoding it? It's possible you're getting a different result from the server that doesn't have adata
key
– Craig Siemens
Nov 22 at 17:20
The picture I added here is actually taken from a print.
– ConnorM
Nov 22 at 17:41
See my edit above
– Craig Siemens
Nov 22 at 17:43
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53435448%2fmarvel-api-swift4-json-decoding%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
In the JSON, data
contains the results
key. The way your keys are set up, it's expecting results
to contain a data
key.
CharactersContainer.CodingKeys.characters
should probably be "data"
Characters.CodingKeys.characters
should probably be "results"
Edit:
There's another issue in Character
. It is trying to get a contain keyed by CharactersContainer.CodingKeys.self
but it should probably be Character.CodingKeys.self
You're right, but if u change it. I still get an error saying: Thread 5: Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "data", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), CodingKeys(stringValue: "results", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "Cannot get KeyedDecodingContainer<CodingKeys> -- no value found for key CodingKeys(stringValue: "data", intValue: nil) ("data")", underlyingError: nil))
– ConnorM
Nov 22 at 17:09
Can you convertdata
to a string and print it out before you try decoding it? It's possible you're getting a different result from the server that doesn't have adata
key
– Craig Siemens
Nov 22 at 17:20
The picture I added here is actually taken from a print.
– ConnorM
Nov 22 at 17:41
See my edit above
– Craig Siemens
Nov 22 at 17:43
add a comment |
up vote
0
down vote
In the JSON, data
contains the results
key. The way your keys are set up, it's expecting results
to contain a data
key.
CharactersContainer.CodingKeys.characters
should probably be "data"
Characters.CodingKeys.characters
should probably be "results"
Edit:
There's another issue in Character
. It is trying to get a contain keyed by CharactersContainer.CodingKeys.self
but it should probably be Character.CodingKeys.self
You're right, but if u change it. I still get an error saying: Thread 5: Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "data", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), CodingKeys(stringValue: "results", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "Cannot get KeyedDecodingContainer<CodingKeys> -- no value found for key CodingKeys(stringValue: "data", intValue: nil) ("data")", underlyingError: nil))
– ConnorM
Nov 22 at 17:09
Can you convertdata
to a string and print it out before you try decoding it? It's possible you're getting a different result from the server that doesn't have adata
key
– Craig Siemens
Nov 22 at 17:20
The picture I added here is actually taken from a print.
– ConnorM
Nov 22 at 17:41
See my edit above
– Craig Siemens
Nov 22 at 17:43
add a comment |
up vote
0
down vote
up vote
0
down vote
In the JSON, data
contains the results
key. The way your keys are set up, it's expecting results
to contain a data
key.
CharactersContainer.CodingKeys.characters
should probably be "data"
Characters.CodingKeys.characters
should probably be "results"
Edit:
There's another issue in Character
. It is trying to get a contain keyed by CharactersContainer.CodingKeys.self
but it should probably be Character.CodingKeys.self
In the JSON, data
contains the results
key. The way your keys are set up, it's expecting results
to contain a data
key.
CharactersContainer.CodingKeys.characters
should probably be "data"
Characters.CodingKeys.characters
should probably be "results"
Edit:
There's another issue in Character
. It is trying to get a contain keyed by CharactersContainer.CodingKeys.self
but it should probably be Character.CodingKeys.self
edited Nov 22 at 17:43
answered Nov 22 at 17:02
Craig Siemens
9,11111839
9,11111839
You're right, but if u change it. I still get an error saying: Thread 5: Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "data", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), CodingKeys(stringValue: "results", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "Cannot get KeyedDecodingContainer<CodingKeys> -- no value found for key CodingKeys(stringValue: "data", intValue: nil) ("data")", underlyingError: nil))
– ConnorM
Nov 22 at 17:09
Can you convertdata
to a string and print it out before you try decoding it? It's possible you're getting a different result from the server that doesn't have adata
key
– Craig Siemens
Nov 22 at 17:20
The picture I added here is actually taken from a print.
– ConnorM
Nov 22 at 17:41
See my edit above
– Craig Siemens
Nov 22 at 17:43
add a comment |
You're right, but if u change it. I still get an error saying: Thread 5: Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "data", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), CodingKeys(stringValue: "results", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "Cannot get KeyedDecodingContainer<CodingKeys> -- no value found for key CodingKeys(stringValue: "data", intValue: nil) ("data")", underlyingError: nil))
– ConnorM
Nov 22 at 17:09
Can you convertdata
to a string and print it out before you try decoding it? It's possible you're getting a different result from the server that doesn't have adata
key
– Craig Siemens
Nov 22 at 17:20
The picture I added here is actually taken from a print.
– ConnorM
Nov 22 at 17:41
See my edit above
– Craig Siemens
Nov 22 at 17:43
You're right, but if u change it. I still get an error saying: Thread 5: Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "data", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), CodingKeys(stringValue: "results", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "Cannot get KeyedDecodingContainer<CodingKeys> -- no value found for key CodingKeys(stringValue: "data", intValue: nil) ("data")", underlyingError: nil))
– ConnorM
Nov 22 at 17:09
You're right, but if u change it. I still get an error saying: Thread 5: Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "data", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), CodingKeys(stringValue: "results", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "Cannot get KeyedDecodingContainer<CodingKeys> -- no value found for key CodingKeys(stringValue: "data", intValue: nil) ("data")", underlyingError: nil))
– ConnorM
Nov 22 at 17:09
Can you convert
data
to a string and print it out before you try decoding it? It's possible you're getting a different result from the server that doesn't have a data
key– Craig Siemens
Nov 22 at 17:20
Can you convert
data
to a string and print it out before you try decoding it? It's possible you're getting a different result from the server that doesn't have a data
key– Craig Siemens
Nov 22 at 17:20
The picture I added here is actually taken from a print.
– ConnorM
Nov 22 at 17:41
The picture I added here is actually taken from a print.
– ConnorM
Nov 22 at 17:41
See my edit above
– Craig Siemens
Nov 22 at 17:43
See my edit above
– Craig Siemens
Nov 22 at 17:43
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53435448%2fmarvel-api-swift4-json-decoding%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Basically don't
try!
while developing JSON parsing withCodable
. Add ado - catch
block and print theerror
instance. It might contain more information than the fatal error. And mapping keys to the same property name (characters
) in different structs can be confusing– vadian
Nov 22 at 17:11
Valid criticism. I changed the names of the classes to MarvelData and Result
– ConnorM
Nov 22 at 17:43