JSON Structure for parsing JSON data - ios

I want to parse this JSON,at the top level incoming JSON is an array,how can access to information of dictionary in array?
[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere#april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
}
]
that is my code but I don't know how detect dictionary data.
func profileFromJSONData(data : NSData) -> ProfileResult {
do{
let jsonObject : [[String:AnyObject]]
= try NSJSONSerialization.JSONObjectWithData(data, options: []) as! [[String:AnyObject]]
for profileJSON in jsonObject {
if let profile = profileFromJsonObject(profileJSON) {
finalProfile.append(profile)
}
}
return .Success(finalProfile)
}
catch let error {
return .Failure(error)
}
}
it is my profileFromJsonObject method for parse JSON into profile instance
func profileFromJsonObject(json: [String:AnyObject]) -> UserProfile?{
guard let
id = json["id"] as? Int,
name = json["name"] as? String,
userName = json["username"] as? String,
email = json["email"] as? String,
address = json["address"] as? NSDictionary,
phone = json["phone"] as? String,
website = json["website"] as? String,
company = json["company"] as? NSDictionary
else {
return nil
}
let obj = UserProfile(id: id, name: name, userName: userName, email: email, address: address, phone: phone, website: website, company: company)
return obj
}

I tried your JSON by taking it in local file, and I am able to parse to the model object in following way.
You just put your remote JSON in my code, i hope it will work
func getTheLocalJSON()
{
let filePath = NSBundle.mainBundle().pathForResource("test", ofType: "json");
let data = NSData.init(contentsOfFile: filePath!);
var json : NSArray!
do{
json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments) as! NSArray;
}catch{
}
print("json \(json)");
let dictResponse = json.objectAtIndex(0) as! NSDictionary;
let objUser = profileFromJsonObject(dictResponse)! as UserProfile;
print("user : \(objUser)");
//Code to access company name and show it as screen title
self.title = (objUser.company)!["name"] as? String;
lblCompanyname.text = (objUser.company)!["name"] as? String;
lblCatchPhrase.text = (objUser.company)!["catchPhrase"] as? String;
lblbs.text = (objUser.company)!["bs"] as? String;
}
func profileFromJsonObject(json: NSDictionary) -> UserProfile?{
guard let
id = json["id"] as? Int,
name = json["name"] as? String,
userName = json["username"] as? String,
email = json["email"] as? String,
address = json["address"] as? NSDictionary,
phone = json["phone"] as? String,
website = json["website"] as? String,
company = json["company"] as? NSDictionary
else {
return nil
}
let obj = UserProfile(id: id, name: name, userName: userName, email: email, address: address, phone: phone, website: website, company: company)
return obj
}
Output :

Related

Fetch and Check internal (Local) JSON file in swift

I want to check city name From local JSON if found then massage show "You got it". But one problem came occurred that is I fetch data from file is successfully but I'd know how to compare it.
Here is my JSON file look like:
{
"data": [
{
"zip_code": 55001,
"latitude": 44.90717,
"longitude": -92.816193,
"city": "Afton",
"state": "MN",
"county": "Washington"
},
{
"zip_code": 55002,
"latitude": 45.513447,
"longitude": -92.894239,
"city": "Almelund",
"state": "MN",
"county": "Chisago"
}
]
}
Code is here:
func FatchingInformation(){
do {
if let file = Bundle.main.url(forResource: "Zone", withExtension: "json") {
let data = try Data(contentsOf: file)
let json = try JSONSerialization.jsonObject(with: data, options: [])
if let object = json as? [String: Any] {
// This condition work and Get JSON on Debug Area
print("Obj is ::: \(object)")
} else if let object = json as? [Any] {
// json is an array
print("Object is \(object)")
} else {
print("JSON is invalid")
}
} else {
print("no file")
}
} catch {
print(error.localizedDescription)
}
}
you are in right way on your JSON is dict of array of dictionary, you need to iterate your [String: Any] first there after check it contains array or dict then you need to follow as below
if let object = json as? [String: Any], let objectArray = object["data"] as? [[String: Any]] {
// do stuff
for getDictItems in objectArray{
if let getCityCompare = getDictItems["city"] as? String, !getCityCompare.isEmpty, getCityCompare == "Almelund"{
print("city name is \(getCityCompare)")
break
}
}
}
You ca use decodable Struct to decode json
// MARK: - Address
struct Address: Codable {
let data: [Datum]
}
// MARK: - Datum
struct Datum: Codable {
let zipCode: Int
let latitude, longitude: Double
let city, state, county: String
enum CodingKeys: String, CodingKey {
case zipCode = "zip_code"
case latitude, longitude, city, state, county
}
}
let address = try? JSONDecoder().decode(Address.self, from: jsonData)

Looping an array received from service

JSON from service
{
"firstname": "Utku",
"lastname": "Dalmaz",
"photos": [{
"src": "image",
"post_id": "69"
}, {
"src": "image",
"post_id": "74"
}, {
"src": "image",
"post_id": "133"
}, {
"src": "image",
"post_id": "142"
}]}
SWIFT CODE
Alamofire.request("SERVICE", method: .post, parameters: parameters).validate().responseJSON { response in
switch response.result {
case .success:
if let json = response.result.value {
var success = 0
if let dictJSON = json as? [String: AnyObject] {
if let successInteger = dictJSON["success"] as? Int {
success = successInteger
if success == 1
{
self.firstname = dictJSON["firstname"] as! String
self.lastname = dictJSON["lastname"] as! String
if let photos = dictJSON["photos"] as! Array<String> {
let postID = //post_id data
let src = //src data
let data = InboxPhotos(ID: postID!, src: src!)
self.photosArr.append(data)
}
...
I am trying to get array data from JSON service. Even though I am able to get firstname and lastname data, I cannot get and loop photos array in swift code.
How can I loop photos array and get post_id and src data into InboxPhotos and append to photosArr array?
let dictJSON = ...
guard let photos = dictJSON?["photos"] as? [[String: Any]] else { return }
let list = photos.map { InboxPhotos(ID: $0["post_id"] as! String, src: $0["src"] as! String)}
// Or more safely.
let list2: [InboxPhotos] = photos.compactMap {
guard let src = $0["src"] as? String,
let id = $0["post_id"] as? String else {
return nil
}
return InboxPhotos(ID: id, src: src)
}
I have made JSON parsing modal for your JSON Data-Type. you don't need anything just pass data at the time create a modal object and get data without hectic.
struct UserModal{
var firstname:String
var lastname:String
var photos: [PhotosModal]
init(dictData:[String: Any]) {
self.firstname = dictData["firstname"] as? String ?? ""
self.lastname = dictData["lastname"] as? String ?? ""
var photosArr = [PhotosModal]()
for data in dictData["photos"] as? [[String:Any]] ?? [] {
photosArr.append(PhotosModal(src: data["src"] as! String, post_id: data["post_id"] as! Int))
}
self.photos = photosArr
}
}
struct PhotosModal{
var src:String
var post_id:Int
init(src:String, post_id:Int) {
self.src = src
self.post_id = post_id
}
}
let userModal = UserModal(dict: dictJSON?["photos"] as? [[String: Any]])
So Make separate file for this modal file. Applying this you will follow Single responsibility class/file of SOLID principal rules.

How to parse Array of JSON to array in Swift

I'm trying to parse JSON which is like below
[
{
"People": [
"Jack",
"Jones",
"Rock",
"Taylor",
"Rob"
]
},
{
"People": [
"Rose",
"John"
]
},
{
"People": [
"Ted"
]
}
]
to an array which results in:
[ ["Jack", "Jones", "Rock", "Taylor", "Rob"] , ["Rose", "John"], ["Ted"] ]
which is array of arrays.
I tried with code below
if let path = Bundle.main.path(forResource: "People", ofType: "json") {
let peoplesArray = try! JSONSerialization.jsonObject(
with: Data(contentsOf: URL(fileURLWithPath: path)),
options: JSONSerialization.ReadingOptions()
) as? [AnyObject]
for people in peoplesArray! {
print(people)
}
}
when I print "people" I get o/p as
{
People = (
"Jack",
"Jones",
"Rock",
"Taylor",
"Rob"
);
}
{
People = (
"Rose",
"John"
);
}
...
I'm confused how to parse when it has "People" repeated 3 times
Trying to display content in UITableView where my 1st cell has "Jack" .."Rob" and Second cell has "Rose" , "John" and third cell as "Ted"
PLease help me to understand how to achieve this
You can do this in an elegant and type safe way leveraging Swift 4 Decodable
First define a type for your people array.
struct People {
let names: [String]
}
Then make it Decodable, so that it can be initialised with a JSON.
extension People: Decodable {
private enum Key: String, CodingKey {
case names = "People"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Key.self)
self.names = try container.decode([String].self, forKey: .names)
}
}
Now you can easily decode your JSON input
guard
let url = Bundle.main.url(forResource: "People", withExtension: "json"),
let data = try? Data(contentsOf: url)
else { /* Insert error handling here */ }
do {
let people = try JSONDecoder().decode([People].self, from: data)
} catch {
// I find it handy to keep track of why the decoding has failed. E.g.:
print(error)
// Insert error handling here
}
Finally to get get your linear array of names you can do
let names = people.flatMap { $0.names }
// => ["Jack", "Jones", "Rock", "Taylor", "Rob", "Rose", "John", "Ted"]
var peoplesArray:[Any] = [
[
"People": [
"Jack",
"Jones",
"Rock",
"Taylor",
"Rob"
]
],
[
"People": [
"Rose",
"John"
]
],
[
"People": [
"Ted"
]
]
]
var finalArray:[Any] = []
for peopleDict in peoplesArray {
if let dict = peopleDict as? [String: Any], let peopleArray = dict["People"] as? [String] {
finalArray.append(peopleArray)
}
}
print(finalArray)
output:
[["Jack", "Jones", "Rock", "Taylor", "Rob"], ["Rose", "John"], ["Ted"]]
In your case, it will be:
if let path = Bundle.main.path(forResource: "People", ofType: "json") {
let peoplesArray = try! JSONSerialization.jsonObject(with: Data(contentsOf: URL(fileURLWithPath: path)), options: JSONSerialization.ReadingOptions()) as? [Any]
var finalArray:[Any] = []
for peopleDict in peoplesArray {
if let dict = peopleDict as? [String: Any], let peopleArray = dict["People"] as? [String] {
finalArray.append(peopleArray)
}
}
print(finalArray)
}
let assume that the json is the encoded data
var arrayOfData : [String] = []
dispatch_async(dispatch_get_main_queue(),{
for data in json as! [Dictionary<String,AnyObject>]
{
let data1 = data["People"]
arrayOfData.append(data1!)
}
})
You can now use the arrayOfData. :D
what you have here is first an array of 3 objects. each object is a dictionary where the key is people and the value is an array of strings. when you're trying to do jsonserialization, you have to cast it down to the expected result. So you have first an array of objects, then you have a dictionary with String: Any, then you obtain an array of String
let peoplesArray = try! JSONSerialization.jsonObject(with: Data(contentsOf: URL(fileURLWithPath: path)), options: []) as? [AnyObject]
guard let peoplesObject = peoplesArray["people"] as? [[String:Any]] else { return }
for people in peoplesObject {
print("\(people)")
}
I couldn't pasted it in a comment, it is too long or something
static func photosFromJSONObject(data: Data) -> photosResult {
do {
let jsonObject: Any =
try JSONSerialization.jsonObject(with: data, options: [])
print(jsonObject)
guard let
jsonDictionary = jsonObject as? [NSObject: Any] as NSDictionary?,
let trackObject = jsonDictionary["track"] as? [String: Any],
let album = trackObject["album"] as? [String: Any],
let photosArray = album["image"] as? [[String: Any]]
else {
return .failure(lastFMError.invalidJSONData)
}
}
}
And the json was something like:
{
artist: {
name: Cher,
track: {
title: WhateverTitle,
album: {
title: AlbumWhatever,
image: {
small: "image.px",
medium: "image.2px",
large: "image.3px"}
....

JSON structure with Swift and Alamofire

Following on from This question
I am trying to bring in the summary field but it has a further value. I have brought in the title and author as follows:
func parseData(JSONData : Data) {
do {
var readableJSON = try JSONSerialization.jsonObject(with: JSONData, options: .mutableContainers) as! JSONstandard
// print(readableJSON)
if let posts = readableJSON["posts"] as? [JSONstandard] {
for post in posts {
let title = post["title"] as! String
let author = post["author"] as! String
let summary = post["summary"] as! String
print(author)
if let imageUrl = post["image"] as? String {
let mainImageURL = URL(string: imageUrl )
let mainImageData = NSData(contentsOf: mainImageURL!)
let mainImage = UIImage(data: mainImageData as! Data)
postsinput.append(postinput.init(mainImage: mainImage, name: title, author: author, summary: summary))
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
catch {
print(error)
}
}
But if i try the summary that way a error is returned. Any help would be appreciated.
JSON STRUCTURE
{
"posts" : [{
"id": "000000",
"url": "/content/interview2",
"date": "2016-11-03 09:01:41",
"modified": "2016-11-03 09:03:47",
"title": "An interview",
"image": "https://www.example.com/sites/default/files/oregood.jpeg",
"summary": {
"value": "<p>Latin text here</p>",
"format": "filtered_html"
}
}]
}
From your previous question response, summary key contains the Dictionary so you can try like this.
guard let dic = post["summary"] as? [String: Any], let summary = dic["value"] as? String else {
return
}

Parsing JSON Data

I want to parse this JSON :http://jsonplaceholder.typicode.com/users
I have a problem for find JSON structure.
I am trying JSON with this structure that is work well, but I don't sure of this is better way or is not!
what is the best way for parsing this JSON array to post instance?
there is my code:
func profileFromJSONData(data : NSData) -> ProfileResult {
do{
let jsonObject : NSArray!
= try NSJSONSerialization.JSONObjectWithData(data, options: []) as! NSArray
for profileJSON in jsonObject {
if let profile = profileFromJsonObject(profileJSON as! NSDictionary) {
finalProfile.append(profile)
}
}
return .Success(finalProfile)
}
catch let error {
return .Failure(error)
}
}
func profileFromJsonObject(json: NSDictionary) -> UserProfile?{
guard let
id = json["id"] as? Int,
name = json["name"] as? String,
userName = json["username"] as? String,
email = json["email"] as? String,
address = json["address"] as? NSDictionary,
phone = json["phone"] as? String,
website = json["website"] as? String,
company = json["company"] as? NSDictionary
else {
return nil
}
let obj = UserProfile(id: id, name: name, userName: userName, email: email, address: address, phone: phone, website: website, company: company)
return obj
}
Here is what apple suggestion when Working with JSON in Swift,
and you can improve your code to one line by using flatMap
change from:
for profileJSON in jsonObject {
if let profile = profileFromJsonObject(profileJSON) {
finalProfile.append(profile)
}
}
to:
finalProfile += jsonObject.flatMap(profileFromJsonObject)
That's the same.
Deal with address:
struct Address {
var street: String
var city: String
...
init?(json: [String: AnyObject]){...}
}
extension Address: CustomStringConvertible {
var description: String {
return "street: \(street), city: \(city)"
}
}
func profileFromJsonObject(json: [String: AnyObject]) -> UserProfile? {
guard let
...
addressJson = json["address"] as? [String: AnyObject]
address = Address(json: addressJson),
...
else {
return nil
}
let obj = UserProfile(id: id, name: name, userName: userName, email: email, address: address, phone: phone, website: website, company: company)
print(address) // output: "street: Kulas Light, city: Gwenborough"
}

Resources