I'm trying to parse JSON that I'm getting from an API using SwiftyJSON and it's giving me this error:
Optional(Error Domain=SwiftyJSONErrorDomain Code=901 "Dictionary["data"] failure, It is not an dictionary" UserInfo={NSLocalizedDescription=Dictionary["data"] failure, It is not an dictionary})
The JSON:
{
"status": 200,
"error": "",
"data": {
"cursusses": [
{
"cursus": {
"curId": 1,
"curNaam": "Lightroom Tips & Tricks",
"catId": 1,
"curInfo": "Praktische en korte Tips en Tricks om sneller en prettiger met Lightroom te kunnen werken.",
"curThumbnail": "lr5-tips-en-tricks.jpg"
}
},
{
"cursus": {
"curId": 2,
"curNaam": "Lightroom Fotobewerkingen",
"catId": 1,
"curInfo": "Per video wordt er in deze cursus een nabewerking uitgevoerd op een foto. Een leerzame manier om te zien hoe je in de praktijk foto's kunt nabewerken terwijl je daarnaast veel praktische tips krijgt over het gebruik van Lightroom 5.",
"curThumbnail": "lr5-bewerkingen.jpg"
}
},
{
"cursus": {
"curId": 3,
"curNaam": "Photoshop Fotobewerkingen",
"catId": 2,
"curInfo": "Per video wordt er in deze cursus een nabewerking uitgevoerd op een foto. Een leerzame manier om te zien hoe je in de praktijk foto's kunt nabewerken terwijl je daarnaast veel praktische tips krijgt over het gebruik van Photoshop.",
"curThumbnail": "photoshop-cc.jpg"
}
},
{
"cursus": {
"curId": 4,
"curNaam": "Basiscursus Lightroom 5",
"catId": 1,
"curInfo": "Leer de basisvaardigheden voor het werken met Adobe Photoshop Lightroom. Over het werken met catalogussen, importeren, het selectieproces, de nabewerking en het exporteren.",
"curThumbnail": "basiscursus-lightroom-5.jpg"
}
},
{
"cursus": {
"curId": 5,
"curNaam": "Photofacts Academy",
"catId": 3,
"curInfo": "Toelichting over het gebruiken van de Photofacts Academy website.",
"curThumbnail": "photofacts-academy.jpg"
}
},
{
"cursus": {
"curId": 6,
"curNaam": "Lightroom 5 web module",
"catId": 1,
"curInfo": "Met de Lightroom web module kun je eenvoudig van je foto's een online galerij maken.",
"curThumbnail": "lr5-web-intro.jpg"
}
},
{
"cursus": {
"curId": 7,
"curNaam": "Photoshop Tips & Tricks",
"catId": 2,
"curInfo": "Praktische tips voor het gebruik van Adobe Photoshop CC.",
"curThumbnail": "photoshop-cc-splash.jpg"
}
}
]
}
}
I'm currently trying to use this block of code to parse the data, this function is called in the completionHandler of an Alamofire request:
func succesCurResponse(let response : Response<String, NSError>) {
if let value = response.result.value {
let json = JSON(value)
let error = json["error"].stringValue
print(json["data"].error)
if(error.isEmpty) {
for(var i = 0; i < json["data"]["cursusses"].count; i++) {
let name = json["data"]["cursusses"][i]["cursus"]["curNaam"].stringValue
let id = json["data"]["cursusses"][i]["cursus"]["curId"].intValue
let catId = json["data"]["cursusses"][i]["cursus"]["catId"].intValue
let info = json["data"]["cursusses"][i]["cursus"]["curInfo"].stringValue
let thumbnail = json["data"]["cursusses"][i]["cursus"]["curThumbnail"].stringValue
let newCur = Cursus()
newCur.ID = id
newCur.name = name
newCur.info = info
newCur.thumbnail = thumbnail
}
}
else {
print(error)
}
}
}
Any suggestions?
Sorry, I don't know Swift. But the following Objective-C code will help you to resolve your issue.
Objective-C :
NSArray *cursussesArray = json[#"cursusses"];
for (NSDictionary *singlecursusseDict in cursussesArray) {
NSLog(#"%#", singlecursusseDict);
NSDictionary *cursus = singlecursusseDict[#"cursus"];
}
I give a try in Swift
let cursussesArray:NSArray = json[“cursusses”]
for singlecursusseDict: NSDictionary in cursussesArray {
print(singlecursusseDict)
cursusDict: NSDictionary = json[“cursus”]
print(cursusDict)
}
Related
I have an App that were built in Ionic Cordova. Recently I change it to Ionic Capacitor. With this change, i've been trying to incorporate an Apple Login but it doesn't working correctly: Apple returns the token but with empty data (email, familyName, etc, all of these returns null). What would be happening?
This is my implementation:
openAppleSignIn() {
const { SignInWithApple } = Plugins;
SignInWithApple.Authorize()
.then(async (res) => {
const respuesta =JSON.stringify(res.response)
let obje = JSON.parse(respuesta)
//alert(obje.identityToken)
//alert(res.response.email)
//alert(JSON.stringify(obje.email))
if (obje && obje.identityToken) {
this.user = obje;
this.server.providerLogin({profile:{email:obje.email,first_name:obje.givenName,last_name:obje.familyName,name:obje.givenName,given_name:obje.givenName,family_name:obje.familyName}}, 'Google').subscribe((response2:any) => {
alert(JSON.stringify({profile:{email:obje.email,first_name:obje.givenName,last_name:obje.familyName,name:obje.givenName,given_name:obje.givenName,family_name:obje.familyName}}))
if(response2.msg != "done")
{
this.presentToast(response2.msg, 'warning');
}
else
{
if(response2.user_id){
localStorage.setItem('user_id',response2.user_id);
this.events.publish('user_login', response2.user_id);
this.presentToast("Bienvenue !", 'secondary');
this.nav.back();
}
else{
this.presentToast("Une erreur s'est porduite. Merci de bien vouloir réessayer.", 'danger');
}
}
});
//console.log('este es el user',this.user)
} else {
this.presentAlert();
}
})
.catch((response) => {
this.presentAlert();
});
}
I'm trying to decode a JSON, however, my breakpoint goes straight to the Catch Statement instead of print the decode data. What am I doing wrong? What I tried was create another Struct where I unpacked all the Array of Data from JSON, I already did it on previous projects, but for this one something else is wrong. For this project I gotta parse the following properties:
name
abv
url_image
JSON
[
{
"id":1,
"name":"Buzz",
"tagline":"A Real Bitter Experience.",
"first_brewed":"09/2007",
"description":"A light, crisp and bitter IPA brewed with English and American hops. A small batch brewed only once.",
"image_url":"https://images.punkapi.com/v2/keg.png",
"abv":4.5,
"ibu":60,
"target_fg":1010,
"target_og":1044,
"ebc":20,
"srm":10,
"ph":4.4,
"attenuation_level":75,
"volume":{
"value":20,
"unit":"liters"
},
"boil_volume":{
"value":25,
"unit":"liters"
},
"method":{
"mash_temp":[
{
"temp":{
"value":64,
"unit":"celsius"
},
"duration":75
}
],
"fermentation":{
"temp":{
"value":19,
"unit":"celsius"
}
},
"twist":null
},
"ingredients":{
"malt":[
{
"name":"Maris Otter Extra Pale",
"amount":{
"value":3.3,
"unit":"kilograms"
}
},
{
"name":"Caramalt",
"amount":{
"value":0.2,
"unit":"kilograms"
}
},
{
"name":"Munich",
"amount":{
"value":0.4,
"unit":"kilograms"
}
}
],
"hops":[
{
"name":"Fuggles",
"amount":{
"value":25,
"unit":"grams"
},
"add":"start",
"attribute":"bitter"
},
{
"name":"First Gold",
"amount":{
"value":25,
"unit":"grams"
},
"add":"start",
"attribute":"bitter"
},
{
"name":"Fuggles",
"amount":{
"value":37.5,
"unit":"grams"
},
"add":"middle",
"attribute":"flavour"
},
{
"name":"First Gold",
"amount":{
"value":37.5,
"unit":"grams"
},
"add":"middle",
"attribute":"flavour"
},
{
"name":"Cascade",
"amount":{
"value":37.5,
"unit":"grams"
},
"add":"end",
"attribute":"flavour"
}
],
"yeast":"Wyeast 1056 - American Ale™"
},
"food_pairing":[
"Spicy chicken tikka masala",
"Grilled chicken quesadilla",
"Caramel toffee cake"
],
"brewers_tips":"The earthy and floral aromas from the hops can be overpowering. Drop a little Cascade in at the end of the boil to lift the profile with a bit of citrus.",
"contributed_by":"Sam Mason <samjbmason>"
},
{
"id":2,
"name":"Trashy Blonde",
"tagline":"You Know You Shouldn't",
"first_brewed":"04/2008",
"description":"A titillating, neurotic, peroxide punk of a Pale Ale. Combining attitude, style, substance, and a little bit of low self esteem for good measure; what would your mother say? The seductive lure of the sassy passion fruit hop proves too much to resist. All that is even before we get onto the fact that there are no additives, preservatives, pasteurization or strings attached. All wrapped up with the customary BrewDog bite and imaginative twist.",
"image_url":"https://images.punkapi.com/v2/2.png",
"abv":4.1,
"ibu":41.5,
"target_fg":1010,
"target_og":1041.7,
"ebc":15,
"srm":15,
"ph":4.4,
"attenuation_level":76,
"volume":{
"value":20,
"unit":"liters"
},
"boil_volume":{
"value":25,
"unit":"liters"
},
"method":{
"mash_temp":[
{
"temp":{
"value":69,
"unit":"celsius"
},
"duration":null
}
],
"fermentation":{
"temp":{
"value":18,
"unit":"celsius"
}
},
"twist":null
},
"ingredients":{
"malt":[
{
"name":"Maris Otter Extra Pale",
"amount":{
"value":3.25,
"unit":"kilograms"
}
},
{
"name":"Caramalt",
"amount":{
"value":0.2,
"unit":"kilograms"
}
},
{
"name":"Munich",
"amount":{
"value":0.4,
"unit":"kilograms"
}
}
],
"hops":[
{
"name":"Amarillo",
"amount":{
"value":13.8,
"unit":"grams"
},
"add":"start",
"attribute":"bitter"
},
{
"name":"Simcoe",
"amount":{
"value":13.8,
"unit":"grams"
},
"add":"start",
"attribute":"bitter"
},
{
"name":"Amarillo",
"amount":{
"value":26.3,
"unit":"grams"
},
"add":"end",
"attribute":"flavour"
},
{
"name":"Motueka",
"amount":{
"value":18.8,
"unit":"grams"
},
"add":"end",
"attribute":"flavour"
}
],
"yeast":"Wyeast 1056 - American Ale™"
},
"food_pairing":[
"Fresh crab with lemon",
"Garlic butter dipping sauce",
"Goats cheese salad",
"Creamy lemon bar doused in powdered sugar"
],
"brewers_tips":"Be careful not to collect too much wort from the mash. Once the sugars are all washed out there are some very unpleasant grainy tasting compounds that can be extracted into the wort.",
"contributed_by":"Sam Mason <samjbmason>"
},
Network Folder
import Foundation
import Alamofire
func getApiData(){
guard let urlString = URL(string: "https://api.punkapi.com/v2/beers") else {
print("URL Error")
return
}
Alamofire.request(urlString).responseJSON { response in
if response.data == response.data{
do{
let decoder = try JSONDecoder().decode(Data.self, from: response.data!)
print(decoder)
}catch{
print(error)
}
}else{print("API Response is Empty")}
}
}
Model Folder
import Foundation
struct Data:Decodable {
let cervejas : [Cerveja]
}
struct Cerveja:Decodable{
let name:String?
let abv:String?
let image_url:String?
}
Try with
let models = try JSONDecoder().decode([Cerveja].self, from: response.data!)
Change the Cerveja class to
let abv:Double?
after successful decoding access them like
for model in models {
print(model.name)
}
I'm trying to identify and handle a specific error that I get as a response from SharePoint rest api, the problem is that the error text depends on the site language.
for example, here is the error in English site:
{
"error": {
"code": "-2147024809, System.ArgumentException",
"message": {
"lang": "en-US",
"value": "Feature '[guid]' for list template '[number]' is not installed in this farm. The operation could not be completed."
}
}
}
and in French site I get:
{
"error": {
"code": "-2147024809, System.ArgumentException",
"message": {
"lang": "fr-FR",
"value": "La fonctionnalité « [guid] » pour le modèle de liste « [number] » n'est pas installée sur cette batterie de serveurs. L'opération n'a pas pu être effectuée."
}
}
}
Is it possible to get the English text regardless of the site language?
I have attached a picture of my JSON tree
{
"-Ko4cg3ik5OFsnLTI4q4" : {
"FacebookPage" : {
"id" : "187736205061418",
"page" : "partyunlimitedtoronto"
},
"MapView" : {
"Edate" : 523940400,
"Sdate" : 523929600,
"intersted" : 3843,
"lat" : 45.510772273476,
"lng" : -73.563586483671,
"type" : "MUSIC",
"userID" : 1373802105986614,
"visibility" : "Public"
},
"address" : "Théâtre Corona",
"bio" : "evenko & Greenland Productions présentent\t\nMogwai\navec/with Xander Harris \nPortes: 19h00 - Spectacle: 20h00\n\nMise en vente: 24 mars à 10h\n\n37$ à 42$\n\nPrix lors de l’achat à la billetterie / Des frais de manutention peuvent s’appliquer lors de l’achat en ligne.\n\n.....................................................\n\nDoors: 7:00 pm - Show: 8:00 pm\n\nOn Sale: March 24 at 10am\n\n$37 to $42\n\nPrices for box office purchase / Handling fees may apply for online purchase.",
"name" : "Mogwai // Montréal",
"pic" : "https://scontent.xx.fbcdn.net/v/t1.0-9/17361785_10155183713782422_6829705267219994059_n.jpg?oh=150f6f53c74233b70b7f1b372c1db1e4&oe=59CF07EE",
"site" : "http://www.evenko.ca/fr/evenements/12392/mogwai/theatre-corona/12-06-2017",
"status" : "normal"
},
"-Ko4cgP2rXJCIRBODWpm" : {
"FacebookPage" : {
"id" : "620998508097068",
"page" : "partyunlimitedtoronto"
},
"MapView" : {
"Edate" : 43223454,
"Sdate" : 65837495,
"interested" : 2355,
"lat" : 45.3846583,
"lng" : -74.4736583,
"type" : "Party",
"userID" : 1373802105986614,
"visibility " : "Public"
},
"address" : "Théâtre Corona",
"bio" : "Greenland Productions & evenko présentent\t\t\t\t\t\t\nNazareth\t\t\t\navec/with Les Deuxluxes\t\n\nPortes: 19h00 - Spectacle: 20h00\n\nMise en vente: 14 avril à midi \n\n44,50$ à 48$\n\nPrix lors de l’achat à la billetterie / Des frais de manutention peuvent s’appliquer lors de l’achat en ligne.\n\n.....................................................\n\nDoors: 7:00 pm - Show: 8:00 pm\n\nOn Sale: April 14 at noon\n\n$44,50 to $48\n\nPrices for box office purchase / Handling fees may apply for online purchase.",
"name" : "Nazareth // Montréal",
"pic" : "https://scontent.xx.fbcdn.net/v/t1.0-9/17759677_10155255160737422_1735715699829358715_n.jpg?oh=1d6d1c250c2c6b38c6ef0de4483bd0a9&oe=5A0C4879",
"site" : "http://www.evenko.ca/fr/evenements/12489/nazareth/theatre-corona/08-03-2017",
"status" : "normal"
}
}
So I'm attempting to only download the "MapView" node inside every child when I run my program but in this case, I won't know the name of the parent of "MapView". Is there any way to only download a specific child like in this case. Otherwise, I was thinking whether I should use this style of structuring.
{
"EventView" : {
"-Ko4cg3ik5OFsnLTI4q4" : {
"FacebookPage" : {
"id" : "187736205061418",
"page" : "partyunlimitedtoronto"
},
"address" : "Théâtre Corona",
"bio" : "evenko & Greenland Productions présentent\t\nMogwai\navec/with Xander Harris \nPortes: 19h00 - Spectacle: 20h00\n\nMise en vente: 24 mars à 10h\n\n37$ à 42$\n\nPrix lors de l’achat à la billetterie / Des frais de manutention peuvent s’appliquer lors de l’achat en ligne.\n\n.....................................................\n\nDoors: 7:00 pm - Show: 8:00 pm\n\nOn Sale: March 24 at 10am\n\n$37 to $42\n\nPrices for box office purchase / Handling fees may apply for online purchase.",
"name" : "Mogwai // Montréal",
"pic" : "https://scontent.xx.fbcdn.net/v/t1.0-9/17361785_10155183713782422_6829705267219994059_n.jpg?oh=150f6f53c74233b70b7f1b372c1db1e4&oe=59CF07EE",
"site" : "http://www.evenko.ca/fr/evenements/12392/mogwai/theatre-corona/12-06-2017",
"status" : "normal"
},
"-Ko4cgP2rXJCIRBODWpm" : {
"FacebookPage" : {
"id" : "620998508097068",
"page" : "partyunlimitedtoronto"
},
"address" : "Théâtre Corona",
"bio" : "Greenland Productions & evenko présentent\t\t\t\t\t\t\nNazareth\t\t\t\navec/with Les Deuxluxes\t\n\nPortes: 19h00 - Spectacle: 20h00\n\nMise en vente: 14 avril à midi \n\n44,50$ à 48$\n\nPrix lors de l’achat à la billetterie / Des frais de manutention peuvent s’appliquer lors de l’achat en ligne.\n\n.....................................................\n\nDoors: 7:00 pm - Show: 8:00 pm\n\nOn Sale: April 14 at noon\n\n$44,50 to $48\n\nPrices for box office purchase / Handling fees may apply for online purchase.",
"name" : "Nazareth // Montréal",
"pic" : "https://scontent.xx.fbcdn.net/v/t1.0-9/17759677_10155255160737422_1735715699829358715_n.jpg?oh=1d6d1c250c2c6b38c6ef0de4483bd0a9&oe=5A0C4879",
"site" : "http://www.evenko.ca/fr/evenements/12489/nazareth/theatre-corona/08-03-2017",
"status" : "normal"
}
},
"MapView" : {
"-Ko4cg3ik5OFsnLTI4q4" : {
"Edate" : 534312000,
"Sdate" : 534301200,
"intersted" : 652,
"lat" : 45.4827983,
"lng" : -73.575107687761,
"type" : "MUSIC",
"userID" : "1373802105986614",
"visibility" : "Public"
},
"-Ko4cgP2rXJCIRBODWpm" : {
"Edate" : 523508400,
"Sdate" : 523497600,
"intersted" : 382,
"lat" : 45.4827983,
"lng" : -73.575107687761,
"type" : "MUSIC",
"userID" : "1373802105986614",
"visibility" : "Public"
}
}
}
where in this case I would have the information in a separate child but where there are parent nodes with the same name in both EventView and MapView.
For the First structure
This structure will definitely make our query download the whole EventView node
var AllMapViews = []; //<-- array of all mapview objects
var path = "/EventView";
firebase.database().ref(path)
.once("value")
.then(eventViews => {
eventViews.forEach(thisevent => {
AllMapViews.push(thisevent.val().MapView);
})
});
Hence the result of the above will look like this
AllMapViews = [
{ "EventDate":343,"Sdate" : 65837495 ..},
{ "EventDate":343,"Sdate" : 65837495 ..},
{ "EventDate":343,"Sdate" : 65837495 ..},
...
]
For the Second structure (My Choice)
This structure will allow our query download only MapViews for all EventViews. Hence, making it the structure of choice in your implementation. Though it will need you to monitor the main EventView nodes often to know when the main event is deleted so that you can also delete it's corresponding MapView.
var AllMapViews = []; //<-- array of all mapview objects
var path = "/MapViews";
firebase.database().ref(path)
.once("value")
.then(mapViews => {
mapViews.forEach(map => {
AllMapViews.push(map.val());
})
});
Hence the result of the above will look like this
AllMapViews = [
{ "EventDate":343,"Sdate" : 65837495 ..},
{ "EventDate":343,"Sdate" : 65837495 ..},
{ "EventDate":343,"Sdate" : 65837495 ..},
...
]
I'm trying to get values from this JSON. This is part of the JSON because the real JSON data is too long.
"hits" : [ {
"recipe" : {
"uri" : "http://www.edamam.com/ontologies/edamam.owl#recipe_bd8def1d09d8c308f659e6945f366271",
"label" : "Pinchos de carne",
"image" : "http://img.recetascomidas.com/recetas/640_480/pinchos-de-carne.jpg",
"source" : "Recetal Comidas",
"url" : "http://pinchos-de-carne.recetascomidas.com/",
"shareAs" : "http://www.edamam.com/recipe/pinchos-de-carne-bd8def1d09d8c308f659e6945f366271/carne",
"yield" : 6.0,
"dietLabels" : [ "Low-Carb" ],
"healthLabels" : [ "Dairy-Free", "Gluten-Free", "Egg-Free", "Peanut-Free", "Tree-Nut-Free", "Soy-Free", "Fish-Free", "Shellfish-Free" ],
"cautions" : [ ],
"ingredientLines" : [ "600 gr. de carne magra de cerdo", "2 cucharadas de pimentón dulce", "1 cucharada de pimentón picante", "1 cucharada de cúrcuma", "1 cucharada de sazonador especial para carnes", "3 cucharadas de perejil fresco bien picadito", "1/2 cucharada de comino", "Aceite de oliva", "3 patatas", "1 diente de ajo", "Pimienta negra", "Sal" ],
"ingredients" : [ {
"text" : "600 gr. de carne magra de cerdo",
"quantity" : 600.0,
"measure" : null,
"food" : "carne magra cerdo",
"weight" : 600.0
}, {
"text" : "2 cucharadas de pimentón dulce",
"quantity" : 2.0,
"measure" : "tbsp",
"food" : "pimenton dulce",
"weight" : 13.6
}, {
"text" : "1 cucharada de pimentón picante",
"quantity" : 1.0,
"measure" : "tbsp",
"food" : "pimenton picante",
"weight" : 6.8
}, {
"text" : "1 cucharada de cúrcuma",
"quantity" : 1.0,
"measure" : "tbsp",
"food" : "curcuma",
"weight" : 6.8
}, {
"text" : "1 cucharada de sazonador especial para carnes",
"quantity" : 1.0,
"measure" : "tbsp",
"food" : "sazonador",
"weight" : 2.7
}, {
"text" : "3 cucharadas de perejil fresco bien picadito",
"quantity" : 3.0,
"measure" : "tbsp",
"food" : "perejil fresco",
"weight" : 11.4
}, {
"text" : "1/2 cucharada de comino",
"quantity" : 0.5,
"measure" : "tbsp",
"food" : "comino",
"weight" : 3.0
}, {
"text" : "Aceite de oliva",
"quantity" : 2.0,
"measure" : "tbsp",
"food" : "aceite oliva",
"weight" : 27.0
}, {
"text" : "3 patatas",
"quantity" : 3.0,
"measure" : null,
"food" : "patatas",
"weight" : 195.0
}, {
"text" : "1 diente de ajo",
"quantity" : 1.0,
"measure" : null,
"food" : "ajo",
"weight" : 3.0
}, {
"text" : "Pimienta negra",
"quantity" : 1.0,
"measure" : "peppercorn",
"food" : "pimienta negra",
"weight" : 0.3
}, {
"text" : "Sal",
"quantity" : 0.0,
"measure" : null,
"food" : "sal",
"weight" : 3.3346887
} ]
For example, I want to get label values that is inside "recipe". I successfully print in console all the JSON, but I don't know how to get recipe values.
I hope you can help me.
This is the code I have now.
let url: String = "https://test-es.edamam.com/search?q=pollo"
var arregloHits: NSMutableArray = []
override func viewDidLoad() {
super.viewDidLoad()
pruebaJson()
}
func pruebaJson(){
if ControladorService.conexionInternet(){
ControladorService.sharedInstance.callUrlWithCompletion(url: url, params: nil, completion: { (finished, response) in
if finished{
let result = NSMutableArray(array: response["hits"] as! NSArray)
self.arregloHits = result
print(self.arregloHits)
}else{
print("Connection failed")
}
}, method: .get)
}else{
print("No Internet")
}
}
Your top level json structure is a dictionary. So you need to parse it into [String: Any]. Then your hints level is a JSON array, so you need to parse it into [Any]
Here is an example. Don't forget to handle unwrap
do{
let json = try JSONSerialization.jsonObject(with: yourJSONData, options: []) as? [String: Any]
let hits = json?["hits"] as? [Any]
dump(hits)
}catch let error{
}