How can I parse this JSON Pokemon Dictionary? Pokemon API (swift 3)
I have an issue with parsing JSON data from new version of the Pokemon API, specifically with values of the "name" in "type" key.
Json looks like this:
"types": [
{
"slot": 2,
"type": {
"name": "poison",
"url": "https://pokeapi.co/api/v2/type/4/"
}
},
{
"slot": 1,
"type": {
"name": "grass",
"url": "https://pokeapi.co/api/v2/type/12/"
}
}
],
"weight": 69
After parsing in Alamofire i'm got the next solution:
if let types = dict["types"] as? [Dictionary<String, String>] , types.count > 0 {
if let type = types[0]["type"] as? Dictionary<String, String> {
if let name = type["name"] {
self._type = name.capitalized
}
}
print("TypeAA: (self._type)")
} else {
self._type = ""
}
And this line also not be executed.
print("TypeAA: (self._type)")
Please advise, how can I parse and get the value of "name" in key named is "type" correctly?
ios json swift parsing
add a comment |
I have an issue with parsing JSON data from new version of the Pokemon API, specifically with values of the "name" in "type" key.
Json looks like this:
"types": [
{
"slot": 2,
"type": {
"name": "poison",
"url": "https://pokeapi.co/api/v2/type/4/"
}
},
{
"slot": 1,
"type": {
"name": "grass",
"url": "https://pokeapi.co/api/v2/type/12/"
}
}
],
"weight": 69
After parsing in Alamofire i'm got the next solution:
if let types = dict["types"] as? [Dictionary<String, String>] , types.count > 0 {
if let type = types[0]["type"] as? Dictionary<String, String> {
if let name = type["name"] {
self._type = name.capitalized
}
}
print("TypeAA: (self._type)")
} else {
self._type = ""
}
And this line also not be executed.
print("TypeAA: (self._type)")
Please advise, how can I parse and get the value of "name" in key named is "type" correctly?
ios json swift parsing
It is much easier to use Decodable instead of manually parsing the response.
– Kamran
Nov 25 '18 at 6:22
Thank @Kamran, but pls advise on these code.
– vaart12345
Nov 25 '18 at 6:24
add a comment |
I have an issue with parsing JSON data from new version of the Pokemon API, specifically with values of the "name" in "type" key.
Json looks like this:
"types": [
{
"slot": 2,
"type": {
"name": "poison",
"url": "https://pokeapi.co/api/v2/type/4/"
}
},
{
"slot": 1,
"type": {
"name": "grass",
"url": "https://pokeapi.co/api/v2/type/12/"
}
}
],
"weight": 69
After parsing in Alamofire i'm got the next solution:
if let types = dict["types"] as? [Dictionary<String, String>] , types.count > 0 {
if let type = types[0]["type"] as? Dictionary<String, String> {
if let name = type["name"] {
self._type = name.capitalized
}
}
print("TypeAA: (self._type)")
} else {
self._type = ""
}
And this line also not be executed.
print("TypeAA: (self._type)")
Please advise, how can I parse and get the value of "name" in key named is "type" correctly?
ios json swift parsing
I have an issue with parsing JSON data from new version of the Pokemon API, specifically with values of the "name" in "type" key.
Json looks like this:
"types": [
{
"slot": 2,
"type": {
"name": "poison",
"url": "https://pokeapi.co/api/v2/type/4/"
}
},
{
"slot": 1,
"type": {
"name": "grass",
"url": "https://pokeapi.co/api/v2/type/12/"
}
}
],
"weight": 69
After parsing in Alamofire i'm got the next solution:
if let types = dict["types"] as? [Dictionary<String, String>] , types.count > 0 {
if let type = types[0]["type"] as? Dictionary<String, String> {
if let name = type["name"] {
self._type = name.capitalized
}
}
print("TypeAA: (self._type)")
} else {
self._type = ""
}
And this line also not be executed.
print("TypeAA: (self._type)")
Please advise, how can I parse and get the value of "name" in key named is "type" correctly?
ios json swift parsing
ios json swift parsing
edited Nov 25 '18 at 13:15
Peter Brockmann
2,25711924
2,25711924
asked Nov 25 '18 at 5:36
vaart12345vaart12345
163
163
It is much easier to use Decodable instead of manually parsing the response.
– Kamran
Nov 25 '18 at 6:22
Thank @Kamran, but pls advise on these code.
– vaart12345
Nov 25 '18 at 6:24
add a comment |
It is much easier to use Decodable instead of manually parsing the response.
– Kamran
Nov 25 '18 at 6:22
Thank @Kamran, but pls advise on these code.
– vaart12345
Nov 25 '18 at 6:24
It is much easier to use Decodable instead of manually parsing the response.
– Kamran
Nov 25 '18 at 6:22
It is much easier to use Decodable instead of manually parsing the response.
– Kamran
Nov 25 '18 at 6:22
Thank @Kamran, but pls advise on these code.
– vaart12345
Nov 25 '18 at 6:24
Thank @Kamran, but pls advise on these code.
– vaart12345
Nov 25 '18 at 6:24
add a comment |
4 Answers
4
active
oldest
votes
You can't do dict["types"] as? [Dictionary<String, String>] because an item in types can't be cast to Dictionary<String, String>. item has integers like "slot": 2 and dictionaries "type": {...}. So it must be cast to [String : Any] first.
if let types = dict["types"] as? [Any], types.count > 0 {
if let firstObject = (types.first as? [String : Any]),
let type = firstObject["type"] as? [String : String],
let name = type["name"] {
self._type = name.capitalized
}
}
if you want name of each item, you have to loop through the items array.
Your solution works but your statement is wrong.[Dictionary<String, String>]is an array of dictionaries, too. And if you checkfirstthe check for empty is redundant.
– vadian
Nov 25 '18 at 8:38
add a comment |
Or try something similar like this here:
if let types = dict["types"] as? [Any] {
guard types.count > 0 else {
return
}
for elment in types {
if let type = elment["type"] as? [String:Any] {
let name = type["name"] as! String
// Do what you want with it here
}
}
}
add a comment |
You can use AlamofireObjectMapper to parse the JSON response from Alamofire very easily.
class PokemonTypesResponse: Mappable {
var types:[Types]?
var weight:Int?
required init?(map: Map){
}
func mapping(map: Map) {
types <- map["types"]
weight <- map["weight"]
}
}
class Types: Mappable {
var slot:Int?
var name:String?
var url:String?
required init?(map: Map){
}
func mapping(map: Map) {
slot <- map["slot"]
type <- map["type.name"]
url <- mapp["type.url"]
}
}
Perform the request with alamofire and use
.responseArray { (response: DataResponse<[PokemonTypesResponse]>) in
switch response.result {
case .success:
//this is the response as PokemonTypesResponse
response.result.value
case .failure(let error):
print(error)
}
to map the JSON result
I haven't tested it, I wrote it based on my experience.
I hope it works and it's easy to understand.
Thank all for your answers, my issue now be solved.
– vaart12345
Nov 25 '18 at 10:08
add a comment |
Your code doesn't work because the first conditional downcast fails.
The value for key types is [Dictionary<String, Any>] (note the nested dictionary in the JSON) and not [Dictionary<String, String>].
So basically this works
if let types = dict["types"] as? [Dictionary<String, Any>] , types.count > 0 {
if let type = types[0]["type"] as? Dictionary<String, String> {
if let name = type["name"] {
self._type = name.capitalized
}
}
print("TypeAA: (self._type)")
} else {
self._type = ""
}
But the pyramid of doom is cumbersome and never check for an empty array with .count > 0 so this is more efficient
if let types = dict["types"] as? [Dictionary<String, Any>],
let firstType = types.first, let typeInfo = firstType["type"] as? Dictionary<String, String>,
let name = typeInfo["name"] {
self._type = name.capitalized
print("TypeAA:", self._type)
} else {
self._type = ""
}
If you need to consider all names you have to use a loop
if let types = dict["types"] as? [Dictionary<String, Any>] {
for type in types {
if let typeInfo = type["type"] as? Dictionary<String, String>,
let name = typeInfo["name"] {
print("TypeAA:", name)
}
}
} else {
self._type = ""
}
If you want to print all names comma separated use
if let types = dict["types"] as? [Dictionary<String, Any>] {
let names = types.compactMap { type -> String? in
guard let typeInfo = type["type"] as? Dictionary<String, String>,
let name = typeInfo["name"] else { return nil }
return name
}
print(names.joined(separator: ", "))
}
#Vadian, your solution is easy to understand and it works. It is very helpful to me. Thank you so much.
– vaart12345
Nov 25 '18 at 10:07
sorry, i am still confuse.
– vaart12345
Nov 25 '18 at 11:21
sorry, i am still confuse. i use your loop code, but it seem only one type is being got correctly. The console log is like below.</br> TypeAA: poison TypeAA: bug </br>Did arrive here? 2018-11-25 18:27:20.067718+0700 PokeMum[11401:1131765] TIC Read Status [1:0x0]: 1:57 2018-11-25 18:27:20.067883+0700 PokeMum[11401:1131765] TIC Read Status [1:0x0]: 1:57 </br> And my expected is print out: "Poison/Grass" (2 types), how to perform?
– vaart12345
Nov 25 '18 at 11:34
There is no stringbugin the given JSON. AndTypeAA: poison / TypeAA: bugare 2 types. Each type is printed separately.
– vadian
Nov 25 '18 at 11:39
Thnks @vadian, one more question, when using your loop code, how to print out the string like this: "Poison/Grass". I am a newbie, pls advice.
– vaart12345
Nov 25 '18 at 14:41
|
show 2 more comments
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',
autoActivateHeartbeat: false,
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%2f53464948%2fhow-can-i-parse-this-json-pokemon-dictionary-pokemon-api-swift-3%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can't do dict["types"] as? [Dictionary<String, String>] because an item in types can't be cast to Dictionary<String, String>. item has integers like "slot": 2 and dictionaries "type": {...}. So it must be cast to [String : Any] first.
if let types = dict["types"] as? [Any], types.count > 0 {
if let firstObject = (types.first as? [String : Any]),
let type = firstObject["type"] as? [String : String],
let name = type["name"] {
self._type = name.capitalized
}
}
if you want name of each item, you have to loop through the items array.
Your solution works but your statement is wrong.[Dictionary<String, String>]is an array of dictionaries, too. And if you checkfirstthe check for empty is redundant.
– vadian
Nov 25 '18 at 8:38
add a comment |
You can't do dict["types"] as? [Dictionary<String, String>] because an item in types can't be cast to Dictionary<String, String>. item has integers like "slot": 2 and dictionaries "type": {...}. So it must be cast to [String : Any] first.
if let types = dict["types"] as? [Any], types.count > 0 {
if let firstObject = (types.first as? [String : Any]),
let type = firstObject["type"] as? [String : String],
let name = type["name"] {
self._type = name.capitalized
}
}
if you want name of each item, you have to loop through the items array.
Your solution works but your statement is wrong.[Dictionary<String, String>]is an array of dictionaries, too. And if you checkfirstthe check for empty is redundant.
– vadian
Nov 25 '18 at 8:38
add a comment |
You can't do dict["types"] as? [Dictionary<String, String>] because an item in types can't be cast to Dictionary<String, String>. item has integers like "slot": 2 and dictionaries "type": {...}. So it must be cast to [String : Any] first.
if let types = dict["types"] as? [Any], types.count > 0 {
if let firstObject = (types.first as? [String : Any]),
let type = firstObject["type"] as? [String : String],
let name = type["name"] {
self._type = name.capitalized
}
}
if you want name of each item, you have to loop through the items array.
You can't do dict["types"] as? [Dictionary<String, String>] because an item in types can't be cast to Dictionary<String, String>. item has integers like "slot": 2 and dictionaries "type": {...}. So it must be cast to [String : Any] first.
if let types = dict["types"] as? [Any], types.count > 0 {
if let firstObject = (types.first as? [String : Any]),
let type = firstObject["type"] as? [String : String],
let name = type["name"] {
self._type = name.capitalized
}
}
if you want name of each item, you have to loop through the items array.
edited Nov 25 '18 at 8:43
answered Nov 25 '18 at 6:26
BilalBilal
9,94952843
9,94952843
Your solution works but your statement is wrong.[Dictionary<String, String>]is an array of dictionaries, too. And if you checkfirstthe check for empty is redundant.
– vadian
Nov 25 '18 at 8:38
add a comment |
Your solution works but your statement is wrong.[Dictionary<String, String>]is an array of dictionaries, too. And if you checkfirstthe check for empty is redundant.
– vadian
Nov 25 '18 at 8:38
Your solution works but your statement is wrong.
[Dictionary<String, String>] is an array of dictionaries, too. And if you check first the check for empty is redundant.– vadian
Nov 25 '18 at 8:38
Your solution works but your statement is wrong.
[Dictionary<String, String>] is an array of dictionaries, too. And if you check first the check for empty is redundant.– vadian
Nov 25 '18 at 8:38
add a comment |
Or try something similar like this here:
if let types = dict["types"] as? [Any] {
guard types.count > 0 else {
return
}
for elment in types {
if let type = elment["type"] as? [String:Any] {
let name = type["name"] as! String
// Do what you want with it here
}
}
}
add a comment |
Or try something similar like this here:
if let types = dict["types"] as? [Any] {
guard types.count > 0 else {
return
}
for elment in types {
if let type = elment["type"] as? [String:Any] {
let name = type["name"] as! String
// Do what you want with it here
}
}
}
add a comment |
Or try something similar like this here:
if let types = dict["types"] as? [Any] {
guard types.count > 0 else {
return
}
for elment in types {
if let type = elment["type"] as? [String:Any] {
let name = type["name"] as! String
// Do what you want with it here
}
}
}
Or try something similar like this here:
if let types = dict["types"] as? [Any] {
guard types.count > 0 else {
return
}
for elment in types {
if let type = elment["type"] as? [String:Any] {
let name = type["name"] as! String
// Do what you want with it here
}
}
}
answered Nov 25 '18 at 7:18
Mattk90Mattk90
5541615
5541615
add a comment |
add a comment |
You can use AlamofireObjectMapper to parse the JSON response from Alamofire very easily.
class PokemonTypesResponse: Mappable {
var types:[Types]?
var weight:Int?
required init?(map: Map){
}
func mapping(map: Map) {
types <- map["types"]
weight <- map["weight"]
}
}
class Types: Mappable {
var slot:Int?
var name:String?
var url:String?
required init?(map: Map){
}
func mapping(map: Map) {
slot <- map["slot"]
type <- map["type.name"]
url <- mapp["type.url"]
}
}
Perform the request with alamofire and use
.responseArray { (response: DataResponse<[PokemonTypesResponse]>) in
switch response.result {
case .success:
//this is the response as PokemonTypesResponse
response.result.value
case .failure(let error):
print(error)
}
to map the JSON result
I haven't tested it, I wrote it based on my experience.
I hope it works and it's easy to understand.
Thank all for your answers, my issue now be solved.
– vaart12345
Nov 25 '18 at 10:08
add a comment |
You can use AlamofireObjectMapper to parse the JSON response from Alamofire very easily.
class PokemonTypesResponse: Mappable {
var types:[Types]?
var weight:Int?
required init?(map: Map){
}
func mapping(map: Map) {
types <- map["types"]
weight <- map["weight"]
}
}
class Types: Mappable {
var slot:Int?
var name:String?
var url:String?
required init?(map: Map){
}
func mapping(map: Map) {
slot <- map["slot"]
type <- map["type.name"]
url <- mapp["type.url"]
}
}
Perform the request with alamofire and use
.responseArray { (response: DataResponse<[PokemonTypesResponse]>) in
switch response.result {
case .success:
//this is the response as PokemonTypesResponse
response.result.value
case .failure(let error):
print(error)
}
to map the JSON result
I haven't tested it, I wrote it based on my experience.
I hope it works and it's easy to understand.
Thank all for your answers, my issue now be solved.
– vaart12345
Nov 25 '18 at 10:08
add a comment |
You can use AlamofireObjectMapper to parse the JSON response from Alamofire very easily.
class PokemonTypesResponse: Mappable {
var types:[Types]?
var weight:Int?
required init?(map: Map){
}
func mapping(map: Map) {
types <- map["types"]
weight <- map["weight"]
}
}
class Types: Mappable {
var slot:Int?
var name:String?
var url:String?
required init?(map: Map){
}
func mapping(map: Map) {
slot <- map["slot"]
type <- map["type.name"]
url <- mapp["type.url"]
}
}
Perform the request with alamofire and use
.responseArray { (response: DataResponse<[PokemonTypesResponse]>) in
switch response.result {
case .success:
//this is the response as PokemonTypesResponse
response.result.value
case .failure(let error):
print(error)
}
to map the JSON result
I haven't tested it, I wrote it based on my experience.
I hope it works and it's easy to understand.
You can use AlamofireObjectMapper to parse the JSON response from Alamofire very easily.
class PokemonTypesResponse: Mappable {
var types:[Types]?
var weight:Int?
required init?(map: Map){
}
func mapping(map: Map) {
types <- map["types"]
weight <- map["weight"]
}
}
class Types: Mappable {
var slot:Int?
var name:String?
var url:String?
required init?(map: Map){
}
func mapping(map: Map) {
slot <- map["slot"]
type <- map["type.name"]
url <- mapp["type.url"]
}
}
Perform the request with alamofire and use
.responseArray { (response: DataResponse<[PokemonTypesResponse]>) in
switch response.result {
case .success:
//this is the response as PokemonTypesResponse
response.result.value
case .failure(let error):
print(error)
}
to map the JSON result
I haven't tested it, I wrote it based on my experience.
I hope it works and it's easy to understand.
answered Nov 25 '18 at 8:21
Dimitrios KalaitzidisDimitrios Kalaitzidis
19219
19219
Thank all for your answers, my issue now be solved.
– vaart12345
Nov 25 '18 at 10:08
add a comment |
Thank all for your answers, my issue now be solved.
– vaart12345
Nov 25 '18 at 10:08
Thank all for your answers, my issue now be solved.
– vaart12345
Nov 25 '18 at 10:08
Thank all for your answers, my issue now be solved.
– vaart12345
Nov 25 '18 at 10:08
add a comment |
Your code doesn't work because the first conditional downcast fails.
The value for key types is [Dictionary<String, Any>] (note the nested dictionary in the JSON) and not [Dictionary<String, String>].
So basically this works
if let types = dict["types"] as? [Dictionary<String, Any>] , types.count > 0 {
if let type = types[0]["type"] as? Dictionary<String, String> {
if let name = type["name"] {
self._type = name.capitalized
}
}
print("TypeAA: (self._type)")
} else {
self._type = ""
}
But the pyramid of doom is cumbersome and never check for an empty array with .count > 0 so this is more efficient
if let types = dict["types"] as? [Dictionary<String, Any>],
let firstType = types.first, let typeInfo = firstType["type"] as? Dictionary<String, String>,
let name = typeInfo["name"] {
self._type = name.capitalized
print("TypeAA:", self._type)
} else {
self._type = ""
}
If you need to consider all names you have to use a loop
if let types = dict["types"] as? [Dictionary<String, Any>] {
for type in types {
if let typeInfo = type["type"] as? Dictionary<String, String>,
let name = typeInfo["name"] {
print("TypeAA:", name)
}
}
} else {
self._type = ""
}
If you want to print all names comma separated use
if let types = dict["types"] as? [Dictionary<String, Any>] {
let names = types.compactMap { type -> String? in
guard let typeInfo = type["type"] as? Dictionary<String, String>,
let name = typeInfo["name"] else { return nil }
return name
}
print(names.joined(separator: ", "))
}
#Vadian, your solution is easy to understand and it works. It is very helpful to me. Thank you so much.
– vaart12345
Nov 25 '18 at 10:07
sorry, i am still confuse.
– vaart12345
Nov 25 '18 at 11:21
sorry, i am still confuse. i use your loop code, but it seem only one type is being got correctly. The console log is like below.</br> TypeAA: poison TypeAA: bug </br>Did arrive here? 2018-11-25 18:27:20.067718+0700 PokeMum[11401:1131765] TIC Read Status [1:0x0]: 1:57 2018-11-25 18:27:20.067883+0700 PokeMum[11401:1131765] TIC Read Status [1:0x0]: 1:57 </br> And my expected is print out: "Poison/Grass" (2 types), how to perform?
– vaart12345
Nov 25 '18 at 11:34
There is no stringbugin the given JSON. AndTypeAA: poison / TypeAA: bugare 2 types. Each type is printed separately.
– vadian
Nov 25 '18 at 11:39
Thnks @vadian, one more question, when using your loop code, how to print out the string like this: "Poison/Grass". I am a newbie, pls advice.
– vaart12345
Nov 25 '18 at 14:41
|
show 2 more comments
Your code doesn't work because the first conditional downcast fails.
The value for key types is [Dictionary<String, Any>] (note the nested dictionary in the JSON) and not [Dictionary<String, String>].
So basically this works
if let types = dict["types"] as? [Dictionary<String, Any>] , types.count > 0 {
if let type = types[0]["type"] as? Dictionary<String, String> {
if let name = type["name"] {
self._type = name.capitalized
}
}
print("TypeAA: (self._type)")
} else {
self._type = ""
}
But the pyramid of doom is cumbersome and never check for an empty array with .count > 0 so this is more efficient
if let types = dict["types"] as? [Dictionary<String, Any>],
let firstType = types.first, let typeInfo = firstType["type"] as? Dictionary<String, String>,
let name = typeInfo["name"] {
self._type = name.capitalized
print("TypeAA:", self._type)
} else {
self._type = ""
}
If you need to consider all names you have to use a loop
if let types = dict["types"] as? [Dictionary<String, Any>] {
for type in types {
if let typeInfo = type["type"] as? Dictionary<String, String>,
let name = typeInfo["name"] {
print("TypeAA:", name)
}
}
} else {
self._type = ""
}
If you want to print all names comma separated use
if let types = dict["types"] as? [Dictionary<String, Any>] {
let names = types.compactMap { type -> String? in
guard let typeInfo = type["type"] as? Dictionary<String, String>,
let name = typeInfo["name"] else { return nil }
return name
}
print(names.joined(separator: ", "))
}
#Vadian, your solution is easy to understand and it works. It is very helpful to me. Thank you so much.
– vaart12345
Nov 25 '18 at 10:07
sorry, i am still confuse.
– vaart12345
Nov 25 '18 at 11:21
sorry, i am still confuse. i use your loop code, but it seem only one type is being got correctly. The console log is like below.</br> TypeAA: poison TypeAA: bug </br>Did arrive here? 2018-11-25 18:27:20.067718+0700 PokeMum[11401:1131765] TIC Read Status [1:0x0]: 1:57 2018-11-25 18:27:20.067883+0700 PokeMum[11401:1131765] TIC Read Status [1:0x0]: 1:57 </br> And my expected is print out: "Poison/Grass" (2 types), how to perform?
– vaart12345
Nov 25 '18 at 11:34
There is no stringbugin the given JSON. AndTypeAA: poison / TypeAA: bugare 2 types. Each type is printed separately.
– vadian
Nov 25 '18 at 11:39
Thnks @vadian, one more question, when using your loop code, how to print out the string like this: "Poison/Grass". I am a newbie, pls advice.
– vaart12345
Nov 25 '18 at 14:41
|
show 2 more comments
Your code doesn't work because the first conditional downcast fails.
The value for key types is [Dictionary<String, Any>] (note the nested dictionary in the JSON) and not [Dictionary<String, String>].
So basically this works
if let types = dict["types"] as? [Dictionary<String, Any>] , types.count > 0 {
if let type = types[0]["type"] as? Dictionary<String, String> {
if let name = type["name"] {
self._type = name.capitalized
}
}
print("TypeAA: (self._type)")
} else {
self._type = ""
}
But the pyramid of doom is cumbersome and never check for an empty array with .count > 0 so this is more efficient
if let types = dict["types"] as? [Dictionary<String, Any>],
let firstType = types.first, let typeInfo = firstType["type"] as? Dictionary<String, String>,
let name = typeInfo["name"] {
self._type = name.capitalized
print("TypeAA:", self._type)
} else {
self._type = ""
}
If you need to consider all names you have to use a loop
if let types = dict["types"] as? [Dictionary<String, Any>] {
for type in types {
if let typeInfo = type["type"] as? Dictionary<String, String>,
let name = typeInfo["name"] {
print("TypeAA:", name)
}
}
} else {
self._type = ""
}
If you want to print all names comma separated use
if let types = dict["types"] as? [Dictionary<String, Any>] {
let names = types.compactMap { type -> String? in
guard let typeInfo = type["type"] as? Dictionary<String, String>,
let name = typeInfo["name"] else { return nil }
return name
}
print(names.joined(separator: ", "))
}
Your code doesn't work because the first conditional downcast fails.
The value for key types is [Dictionary<String, Any>] (note the nested dictionary in the JSON) and not [Dictionary<String, String>].
So basically this works
if let types = dict["types"] as? [Dictionary<String, Any>] , types.count > 0 {
if let type = types[0]["type"] as? Dictionary<String, String> {
if let name = type["name"] {
self._type = name.capitalized
}
}
print("TypeAA: (self._type)")
} else {
self._type = ""
}
But the pyramid of doom is cumbersome and never check for an empty array with .count > 0 so this is more efficient
if let types = dict["types"] as? [Dictionary<String, Any>],
let firstType = types.first, let typeInfo = firstType["type"] as? Dictionary<String, String>,
let name = typeInfo["name"] {
self._type = name.capitalized
print("TypeAA:", self._type)
} else {
self._type = ""
}
If you need to consider all names you have to use a loop
if let types = dict["types"] as? [Dictionary<String, Any>] {
for type in types {
if let typeInfo = type["type"] as? Dictionary<String, String>,
let name = typeInfo["name"] {
print("TypeAA:", name)
}
}
} else {
self._type = ""
}
If you want to print all names comma separated use
if let types = dict["types"] as? [Dictionary<String, Any>] {
let names = types.compactMap { type -> String? in
guard let typeInfo = type["type"] as? Dictionary<String, String>,
let name = typeInfo["name"] else { return nil }
return name
}
print(names.joined(separator: ", "))
}
edited Nov 25 '18 at 17:54
answered Nov 25 '18 at 8:37
vadianvadian
146k13157175
146k13157175
#Vadian, your solution is easy to understand and it works. It is very helpful to me. Thank you so much.
– vaart12345
Nov 25 '18 at 10:07
sorry, i am still confuse.
– vaart12345
Nov 25 '18 at 11:21
sorry, i am still confuse. i use your loop code, but it seem only one type is being got correctly. The console log is like below.</br> TypeAA: poison TypeAA: bug </br>Did arrive here? 2018-11-25 18:27:20.067718+0700 PokeMum[11401:1131765] TIC Read Status [1:0x0]: 1:57 2018-11-25 18:27:20.067883+0700 PokeMum[11401:1131765] TIC Read Status [1:0x0]: 1:57 </br> And my expected is print out: "Poison/Grass" (2 types), how to perform?
– vaart12345
Nov 25 '18 at 11:34
There is no stringbugin the given JSON. AndTypeAA: poison / TypeAA: bugare 2 types. Each type is printed separately.
– vadian
Nov 25 '18 at 11:39
Thnks @vadian, one more question, when using your loop code, how to print out the string like this: "Poison/Grass". I am a newbie, pls advice.
– vaart12345
Nov 25 '18 at 14:41
|
show 2 more comments
#Vadian, your solution is easy to understand and it works. It is very helpful to me. Thank you so much.
– vaart12345
Nov 25 '18 at 10:07
sorry, i am still confuse.
– vaart12345
Nov 25 '18 at 11:21
sorry, i am still confuse. i use your loop code, but it seem only one type is being got correctly. The console log is like below.</br> TypeAA: poison TypeAA: bug </br>Did arrive here? 2018-11-25 18:27:20.067718+0700 PokeMum[11401:1131765] TIC Read Status [1:0x0]: 1:57 2018-11-25 18:27:20.067883+0700 PokeMum[11401:1131765] TIC Read Status [1:0x0]: 1:57 </br> And my expected is print out: "Poison/Grass" (2 types), how to perform?
– vaart12345
Nov 25 '18 at 11:34
There is no stringbugin the given JSON. AndTypeAA: poison / TypeAA: bugare 2 types. Each type is printed separately.
– vadian
Nov 25 '18 at 11:39
Thnks @vadian, one more question, when using your loop code, how to print out the string like this: "Poison/Grass". I am a newbie, pls advice.
– vaart12345
Nov 25 '18 at 14:41
#Vadian, your solution is easy to understand and it works. It is very helpful to me. Thank you so much.
– vaart12345
Nov 25 '18 at 10:07
#Vadian, your solution is easy to understand and it works. It is very helpful to me. Thank you so much.
– vaart12345
Nov 25 '18 at 10:07
sorry, i am still confuse.
– vaart12345
Nov 25 '18 at 11:21
sorry, i am still confuse.
– vaart12345
Nov 25 '18 at 11:21
sorry, i am still confuse. i use your loop code, but it seem only one type is being got correctly. The console log is like below.</br> TypeAA: poison TypeAA: bug </br>Did arrive here? 2018-11-25 18:27:20.067718+0700 PokeMum[11401:1131765] TIC Read Status [1:0x0]: 1:57 2018-11-25 18:27:20.067883+0700 PokeMum[11401:1131765] TIC Read Status [1:0x0]: 1:57 </br> And my expected is print out: "Poison/Grass" (2 types), how to perform?
– vaart12345
Nov 25 '18 at 11:34
sorry, i am still confuse. i use your loop code, but it seem only one type is being got correctly. The console log is like below.</br> TypeAA: poison TypeAA: bug </br>Did arrive here? 2018-11-25 18:27:20.067718+0700 PokeMum[11401:1131765] TIC Read Status [1:0x0]: 1:57 2018-11-25 18:27:20.067883+0700 PokeMum[11401:1131765] TIC Read Status [1:0x0]: 1:57 </br> And my expected is print out: "Poison/Grass" (2 types), how to perform?
– vaart12345
Nov 25 '18 at 11:34
There is no string
bug in the given JSON. And TypeAA: poison / TypeAA: bug are 2 types. Each type is printed separately.– vadian
Nov 25 '18 at 11:39
There is no string
bug in the given JSON. And TypeAA: poison / TypeAA: bug are 2 types. Each type is printed separately.– vadian
Nov 25 '18 at 11:39
Thnks @vadian, one more question, when using your loop code, how to print out the string like this: "Poison/Grass". I am a newbie, pls advice.
– vaart12345
Nov 25 '18 at 14:41
Thnks @vadian, one more question, when using your loop code, how to print out the string like this: "Poison/Grass". I am a newbie, pls advice.
– vaart12345
Nov 25 '18 at 14:41
|
show 2 more comments
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.
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%2f53464948%2fhow-can-i-parse-this-json-pokemon-dictionary-pokemon-api-swift-3%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
It is much easier to use Decodable instead of manually parsing the response.
– Kamran
Nov 25 '18 at 6:22
Thank @Kamran, but pls advise on these code.
– vaart12345
Nov 25 '18 at 6:24