this post follows an old post where some people helped me for a similar problem.
I currently developing an app which list user object by making an request to a webservice, which send a response in JSON in this format :
{
"objects": [
{
"id": "28",
"title": "test",
"price": "56 €",
"description": "kiki",
"addedDate": "11-07-2015",
"user_id": "1",
"user_name": "CANOVAS",
"user_zipCode": "69330",
"category_id": "1",
"category_label": "VEHICULES",
"subcategory_id": "1",
"subcategory_label": "Voitures",
"picture": "",
"bdd": {},
"picture_url": "http://jdl-barreme-orange.dyndns.org/WEBSERVICE/pictures/test.JPG"
},
{
"id": "27",
"title": "ferrari",
"price": "55 €",
"description": "rouge jantes",
"addedDate": "11-07-2015",
"user_id": "1",
"user_name": "CANOVAS",
"user_zipCode": "69330",
"category_id": "1",
"category_label": "VEHICULES",
"subcategory_id": "1",
"subcategory_label": "Voitures",
"picture": "",
"bdd": {},
"picture_url": "http://jdl-barreme-orange.dyndns.org/WEBSERVICE/pictures/ferrari.JPG"
}
}
I search a method to retrieve for each dictionary the value title and price and put them in a tableView.
Code I used (tableviewcontroller) :
if let jsonArray = NSJSONSerialization.JSONObjectWithData(urlData!, options: nil, error: nil) as? [[String:AnyObject]] {
for dict in jsonArray {
if let title = dict["title"] as? String {
println(title)
}
}
}
But it doesn't work, I put a breakpoint, and Xcode stop to interpret here :
for dict in jsonArray
Thanks for your help.
This example JSON is not valid: it lacks a ] before the last }.
But I guess this is just a pasting typo and the JSON you're using is properly formatted, so your problem is that you need to first access the objects key of your dictionary.
This key holds a value of an array of dictionaries, so we're using it as a typecast:
if let json = NSJSONSerialization.JSONObjectWithData(urlData!, options: nil, error: nil) as? [String:AnyObject] {
if let objects = json["objects"] as? [[String:AnyObject]] {
for dict in objects {
if let title = dict["title"] as? String {
println(title)
}
}
}
}
First we cast the result of NSJSONSerialization.JSONObjectWithData as the dictionary: [String:AnyObject], then we access the value for the objects key, then we cast this value as an array of dictionaries: [[String:AnyObject]].
Remember, with JSON format, dictionaries are formatted with {} and arrays are formatted with [].
Your example is {key:[{},{}]} so it's a dictionary holding an array of dictionaries.
Update for Swift 2.0
if let json = try? NSJSONSerialization.JSONObjectWithData(urlData!, options: []) as? [String:AnyObject] {
if let objects = json?["objects"] as? [[String:AnyObject]] {
for dict in objects {
if let title = dict["title"] as? String {
print(title)
}
}
}
}
Try this :
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(urlData, options: NSJSONReadingOptions.MutableContainers, error: nil) as! NSDictionary
var DataFromJSon = jsonResult["objects"] as! NSArray
for one in DataFromJSon {
var title = one["title"] as! String
println(title)
}
Related
How can I JSON object inside an array in swift4? How ca I get the response for this JSON in swift4? I am printing the location but its's getting nil.
Here its my JSON data:
{
"Details": [{
"phone":
"id":
}],
"address": [{
"location": "some location"
}]
}
do {
let json = try JSONSerialization.jsonObject(with: data!, options: []) as! [String: AnyObject]
let location = json["location"] as? [[String: AnyObject]]
print(location)
} catch {
print("error")
}
json["location"] doesn't exist and therefore is not an array. Location is inside the address array.
try
if let addressArray = json["address"] as? [[String: Any]] {
let address = addressArray.first
let location = address?["location'] as? String
print(location)
}
NOTES
In your JSON location was missing any value i.e "location": I added a String
it's better to use the Codable protocol in Swift 4
Can any one suggest and send me sample code for fetching JSON response. Few APIs I am getting data in the form of the NSDictionary and few APIs I am getting data in the form of NSArray.
This is my API request with Alamofire.
APIManager.sharedInstance.getTeacherProfileDataFromURL(){(userJson)-> Void in
let swiftyJsonVar = JSON(userJson)
print("userJson userJson userJson userJson",userJson)
print("swiftyJsonVar",swiftyJsonVar)
}
1) API WITH JSON ARRAY OF DATA
{
"status": 1,
“student”: [
{
"name": "Sprouse",
"subject": [
“english”
],
"personal_email": "",
"school_email": "cole.sprouse483#demo.in",
"phone": "9665478544",
"class_teacher": false,
"image": "/assets/default_male.png"
},
{
"name": “elen”,
"subject": [
"Social Science"
],
"personal_email": "",
"school_email": "elena.gilbert564#demo.in",
"phone": "9066260799",
"class_teacher": false,
"image": "/assets/default_female.png"
},
],
"message": "Details fetched successfully."
}
2) ANOTHER API WITH JSON DICTIONARY OF DATA
{
"status": 1,
"dashboard": {
"announcement": [
{
"title": "Independence Day Celebration",
"posted_on": "13 August, 2017"
}
],
"student": {
"attendance_percent": 100,
"assignment": [
{
"title": "Alphabets in HINDI",
"end_date": "13/09/2017",
"subject": "Hindi",
"teacher_name": "Bonnie Bennette"
}
],
"leave_apply": 13
},
"image": "/system/images/86/j1f9DiJi_thumb.jpg?1504593436"
},
"message": "Details fetched successfully."
}
1) API WITH JSON ARRAY OF DATA
let swiftyJsonVar = JSON(userJson)
let array : [[String : String]] = swiftyJsonVar["student"]
This will give you an array of dictionaries or key-values of student.
Further you can get another value from the array like that
let name : String = array[0]["name"]
2) ANOTHER API WITH JSON DICTIONARY OF DATA
let swiftyJsonVar = JSON(userJson)
let dictionary : [[String : String]] = swiftyJsonVar["dashboard"]
This will give you an array of dictionary or key-value of dashboard.
let array : [[String : String]] = dictionary["announcement"]
This will give you the array of announcement and next you can get the further values like this
let name : array = array[0]["title"]
i have resolved my issue long back , posting lately this is my answer it may helpful for other thats why i am posting here.
if data is in the form of array.
DispatchQueue.main.async {
TeacherAPIManager.sharedInstance.FetchTeacherStudentAttendanceDataFromURL(){(attendanceJson)-> Void in
print("observationInfo --",attendanceJson)
let swiftyAttendanceJsonVar = JSON(attendanceJson)
let observation = swiftyAttendanceJsonVar["list"].rawString()!
let jsonData = observation.data(using: .utf8)!
let array = try? JSONSerialization.jsonObject(with: jsonData, options: []) as! Array< Any>
for observationVar in array!{
let totlDic = NSMutableDictionary()
let dic = observationVar as! Dictionary<String,Any>
}
}
if data is in the form of dictionary. just replace this below of line code in above function array line.
let dictionary = try? JSONSerialization.jsonObject(with: jsonData, options: []) as! Dictionary<String, Any>
I am currently developing an app and I want to display some information about a particular place. I am using Google Places API to do this and am trying to extract some information from this JSON response:
{
"html_attributions": [],
"result": {
"address_components": [],
"adr_address": "5, \u003cspan class=\"street-address\"\u003e48 Pirrama Rd\u003c/span\u003e, \u003cspan class=\"locality\"\u003ePyrmont\u003c/span\u003e \u003cspan class=\"region\"\u003eNSW\u003c/span\u003e \u003cspan class=\"postal-code\"\u003e2009\u003c/span\u003e, \u003cspan class=\"country-name\"\u003eAustralia\u003c/span\u003e",
"formatted_address": "5, 48 Pirrama Rd, Pyrmont NSW 2009, Australia",
"formatted_phone_number": "(02) 9374 4000",
"geometry": {},
"icon": "https://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png",
"id": "4f89212bf76dde31f092cfc14d7506555d85b5c7",
"international_phone_number": "+61 2 9374 4000",
"name": "Google",
"photos": [],
"place_id": "ChIJN1t_tDeuEmsRUsoyG83frY4",
"rating": 4.5,
"reference": "CmRaAAAAVvEJLOszIgZMqrn59xg_wEmLJUpC52Zd7HZzzcv0OsaRobY_f8galxBVNsyEgC9nhUsI7BQQcTYCA0t_f8JlhEV-dftt-OhapkRRvQ12g6R3FU-d6OWB-T1vYVIcRuEBEhBha4swICH7pUUsjBRivnHTGhT1Y97NAmr0iWe4qffGJH0iY96GKg",
"reviews": [],
"scope": "GOOGLE",
"types": [
"point_of_interest",
"establishment"
],
"url": "https://maps.google.com/?cid=10281119596374313554",
"user_ratings_total": 133,
"utc_offset": 660,
"vicinity": "5 48 Pirrama Road, Pyrmont",
"website": "https://www.google.com.au/about/careers/locations/sydney/"
},
"status": "OK"
}
The code I am using in my view controller is:
let reposURL = NSURL(string: "https://maps.googleapis.com/maps/api/place/details/json?placeid=\(chosenPlaceID!)&key=SOMEAPIKEY")!
if let JSONData = NSData(contentsOfURL: reposURL) {
if let json = (try? NSJSONSerialization.JSONObjectWithData(JSONData, options: [])) as? NSDictionary {
if let reposArray = json["result"] as? [NSDictionary] {
for item in reposArray {
placeRepositories.append(PlaceRepository(json: item ))
}
}
}
}
The code in my placeRepository controller is:
class PlaceRepository {
var name: String?
var formattedAddress: String?
var formattedPhoneNumber: String?
var internationPhoneNumber: String?
var types: [String]?
init(json: NSDictionary) {
self.name = json["name"] as? String
self.formattedAddress = json["formatted_address"] as? String
self.formattedPhoneNumber = json["formatted_phone_number"] as? String
self.internationPhoneNumber = json["international_phone_number"] as? String
self.types = json["types"] as? [String]
}
}
I have put a breakpoint in to try and find out what is going on and the for item in reposArray code is never accessed, it gets skipped over in the previous if statement but I am not sure why? Any help would be greatly appreciated.
Thank you.
Your response suggests json["result"] is not array of dictionary ... [NSDictionary] ... its NSDictionary
change this line
if let reposArray = json["result"] as? [NSDictionary] { ... }
with
if let reposArray = json["result"] as? NSDictionary {
PlaceRepository(json: reposArray )
}
After that you can't loop NSDictionary like
for item in reposArray { .. }
You can use third party libraries like SwiftyJson It's make JSON parsing more easy task.
I have this code but the problem is that I can't get the exact value instead it will give me a null value when i test in in NSLog
func parseJSON() {
let path: String = NSBundle.mainBundle().pathForResource("vehicles", ofType: "json") as String!
let jsonData = NSData(contentsOfFile: path) as NSData!
let readableJSON = JSON(data: jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil)
let Makes = readableJSON["Make"]
NSLog("\(Makes)")
}
and I have the sample JSON object here:
[
{
"id": "56c3fe547816d74d1c34fcaf",
"IDVehicle": "323405",
"IDCustomer": "77",
"Make": "AUDI",
"Model": "A4"
},
{
"id": "56c3fe547816d74d1c34fe2a",
"IDVehicle": "248599",
"IDCustomer": "432307",
"Make": "MAZDA",
"Model": "6"
}
]
NOTE: I'm using the SwiftyJSON from github thanks
You can do that using for loop...
With Index
for (index, element) in enumerate(readableJSON) {
println("Item \(index): \(element["Make"])")
}
or without index
for element in readableJSON{
print("element["Make"]")
}
But make sure that readableJSON is an array.
I have a question regarding when to use NSDictionary & when to use NSArray while you are making a HTTP request and getting JSON data back.
For example if the JSON coming back is an array of objects like below:
[
{object1},
{object2},
.........
]
I have the following line in my code:
if let books:Array<AnyObject> = json[""] as? Array<AnyObject> {
}
Its giving an error:
Array< anyObject >? is not convertible to Array< anyObject >
Parsing:
var json:NSMutableArray = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! NSMutableArray
if (jsonError != nil) {
println("Error parsing json: \(jsonError)")
}
Any idea what I might be doing wrong.
UPDATE:
Currently I have the following code:
class func getBooks(completion: (result:Array<BookSummary>)->()) {
var bookArray = [BookSummary]()
let url = NSURL(string: "http://something.herokuapp.com/user/all")
if let tempUrl:NSURL = url {
let urlReq = NSURLRequest(URL: tempUrl)
let queue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(urlReq, queue: queue, completionHandler: { (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
if (error != nil) {
println("API error: \(error), \(error.userInfo)")
}
var jsonError:NSError?
var newBook = BookSummary(id: "", title: "", fullname: "", thumbnail: "")
if let arr = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) as? [AnyObject] {
for a in arr {
//println(a)
//println( arr[0])
println( arr[0])
}
}
By doing println(arr[0]) I am getting the object at the first index.
But if I try println(arr[0].fullname) it comes up with an error:
any object does not have a member named fullname
If you are using the standard NSJSONSerialization to parse from JSON string you use the JSONObjectWithData() class function.
This returns AnyObject? and can be parsed to either Dictionary or Array.
So if the JSON string starts with "[" its parseable to an Array:
if let arr = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) as? [AnyObject] {
for a in arr {
println(a)
}
// Other options to access the values
println( arr[0] )
println( arr.first )
}
And if it starts with a "{" its parseable to a Dictionary:
if let dict = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) as? [String:AnyObject] {
for (key, value) in dict {
println("\(key) = \(value)")
}
// Other options to access the values
println( dict["someKey"] )
println( dict[dict.keys[0]] )
println( dict[dict.keys.first] )
}
In Swift I recommend you dont use NSDictionary and NSArray and use Swifts own Dictionary and Array instead. Mostly because Swift is so type safe and you can control the types on a Swift Dictionary and Array and not the old NS stuff.
To parse this json data from CDiscount API which contains Products/Price/Name :
{
"ItemCount": "34",
"PageCount": "7",
"PageNumber": "0",
"Products": [
{
"AssociatedProducts": null,
"BestOffer": {
"Condition": "New",
"Id": "MD531NFA",
"IsAvailable": true,
"PriceDetails": {
"Discount": null,
"ReferencePrice": "249.00",
"Saving": {
"Type": "Amount",
"Value": "17.0"
}
},
"ProductURL": "http://www.cdiscount.com/opa.aspx/?trackingid=T1mQnsY6DVL2nQMfDBv95HJiDedNp6Iusby9wMMBIWJ8xCUTe2ax25EOmRJ_4IkI&action=product&id=MD531NFA",
"SalePrice": "231.98",
"Seller": {
"Id": "0",
"Name": "Cdiscount"
},
"Shippings": null,
"Sizes": null
},
"Brand": "APPLE",
"Description": "Tablette tactile avec écran 7,9\" capacitif - Processeur Apple A5 bicoeur - Stockage 16Go - WiFi 802.11 b/g/n - Camera avant 1,2Mpixels - Caméra arrière 5Mpixels - Connecteur Lightning reversible - Jusqu’à 10h d'autonomie - IOS 6 - Garantie 1 an",
"Ean": null,
"Id": "MD531NFA",
"Images": null,
"MainImageUrl": "http://i2.cdscdn.com/pdt2/N/F/A/1/300x300/MD531NFA.jpg",
"Name": "Apple iPad mini Wi-Fi 16 Go blanc & argent",
"Offers": null,
"OffersCount": "10",
"Rating": "4.69"
}
]
}
From this data, I wanted to print the product name and its price.
So I should first parse in the Json object as dictionary in search for 'Products' key, and the results as an AnyObject.
let products: AnyObject = jsonDict["Products"]
Then loop through all products and for each one loop over the dictionary keys
for aProduct in products as! NSArray{
for aKey in (aProduct as! NSDictionary).allKeys{
Based on the json data model, it's enough to print the product name :
if aKey as! String == "Name"{
if let name: AnyObject = aProduct["Name"]{
println("Product : \(name) ->")
}
}
But I need to go deeper in the data tree to print the price as it is stored in another dictionary of dictionary.
if aKey as! String == "BestOffer"{
if let offers: AnyObject = aProduct["BestOffer"]{
for offerDetail in (offers as! NSDictionary).allKeys{
if offerDetail as! String == "SalePrice"{
if let price: AnyObject = offers["SalePrice"]{
println("|--> Price: \(price)")
}
}
}
}
}
So to resume :
// Get data in a swift Dictionary
let jsonDict = NSJSONSerialization.JSONObjectWithData(responseData, options: NSJSONReadingOptions.AllowFragments, error: nil) as? [String: AnyObject]
// Begin navigate through the dictionary (here through 'Products')
if let products: AnyObject = jsonDict["Products"]{
// Get product data through loop in a NSArray
for aProduct in products as! NSArray{
// Loop over keys in one product as NSDictionary
for aKey in (aProduct as! NSDictionary).allKeys{
// test key value
if aKey as! String == "Name"{
// if exists, print product name
if let name: AnyObject = aProduct["Name"]{
println("Product : \(name) ->")
}
}
// another test key value
if aKey as! String == "BestOffer"{
// same as before to get deeper in the json tree structure
if let offers: AnyObject = aProduct["BestOffer"]{
for offerDetail in (offers as! NSDictionary).allKeys{
if offerDetail as! String == "SalePrice"{
if let price: AnyObject = offers["SalePrice"]{
println("|--> Price: \(price)")
}
}
}
}
}
}
}
}
Hope this will help !
Reading your comment, i think you want to look at AFNetworking.
Simple example:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:#"http://example.com/resources.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
// here is where you import the JSON data from responseObject
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
NSDictionary is unsorted, but associative where as NSArray is sorted but index only. One way is to obtain all the keys of the JSON data into an NSArray so the order of the data structure is maintained, then import the data into NSDictionary. Then you can use the value from the keys array to reference the NSDictionary
The example is for Objective-C, however hopefully it will still be relevant