Remote json parsing in Swift - json

[
-{
valid:"2",
invalid: "1",
pending: "2"
},
-{
valid:"0",
invalid: "1",
pending: "0"
},
-{
valid:"2",
invalid: "1",
pending: "2"
}
]
I am trying to parse this remote json and populate the data into an array.
I am struggling for hours trying to find out why my code isn't working,the array always ends up being empty. can somebody please tell me what am i doing wrong ?
var arrayreports : [Report] = []
var report = Report()
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let host = appDelegate.host
if(Reachability.isConnectedToNetwork()){
let postEndpoint: String = host+"/api/reportbyworkflow/7"
let session = NSURLSession.sharedSession()
let url = NSURL(string: postEndpoint)!
session.dataTaskWithURL(url, completionHandler: { ( data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
guard let realResponse = response as? NSHTTPURLResponse where
realResponse.statusCode == 201 else {
print("Bad thing happened")
return
}
do {
if let ipString = NSString(data:data!, encoding: NSUTF8StringEncoding) {
let jsonDictionary:AnyObject! = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
let json = jsonDictionary as? Array<AnyObject>
for index in 0...json!.count-1 {
let contact : AnyObject? = json![index]
print(contact)
let collection = contact! as! Dictionary<String, AnyObject>
let valid = collection["valid"] as! String
let invalid = collection["invalid"] as! String
let pending = collection["pending"] as! String
report!.valid = Double(Int(valid)!)
report!.invalid = Double(Int(invalid)!)
report!.pending = Double(Int(pending)!)
arrayreports.append(report!)
}
}}
catch {
print("bad things happened")
}
}).resume()
}

If your json is really the one you copied here, it is not valid ( check on jsonvalidator.com ).
So it is normal than your serialization returns an empty array

Related

Swift read from JSON dictionary

I am sending an Alamofire request and inside of my completion handler I have:
if let jsonData = response.result.value {
result = jsonData
guard let data = result.data(using: .utf8) else { return}
guard let dictionary = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
print("Could not cast JSON content as a Dictionary<String, Any>")
return
}
print("dictionary: \(dictionary)")
if dictionary["status"] as! String == "false"{
//Do something
}
}
else{
result = "\(response.error)"
}
The result of printing dictionary is ["status":false, "value":A1]. Ultimately I want to use status for my if statement. However I get a crash on the if statement line: if dictionary["status"] as! String == "false" of Fatal error: Unexpectedly found nil while unwrapping an Optional value. I also tried changing the line to if dictionary["status"] as! Bool == false and I get the exact same error.
The json as returned from the request is:
{
"value": "A1",
"status": "false"
}
So my question is, what is the correct way to get the value for status out of dictionary?
Would something like this work?
struct jsonOut: Codable {
let value: String
let status: String
}
if let jsonData = response.result.value {
result = jsonData
guard let data = result.data(using: .utf8)
let status = try JSONDecoder().decode(jsonOut.self, from: data)
}
Since the JSON has the format:
{
"value": "A1",
"status": "false"
}
The correct way is using Codable with the same format as the JSON:
struct jsonOut: Codable {
let value: String
let status: String
}
if let jsonData = response.result.value {
result = jsonData
guard let data = result.data(using: .utf8)
let statusData = try JSONDecoder().decode(jsonOut.self, from: data)
print("status: \(statusData.status)"
}

How to get value of jsonObject inside a jsonObject swift 4?

I use FCM to send push notification to my iOS app.When user click on the notification tray,the data handle by the function below:
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
print(userInfo['data'])
}
The userInfo is a [AnyHashable:Any] type.I successfully get the data from the userInfo['data'].So here is the data structure for userInfo['data'] :
'{"data":
{
"title":"My app",
"message":"The message here",
"payload":{
"post_id":"602"
},
"timestamp":"2018-03-10 14:12:08"
}
}'
Here is how I tried :
if let dataString = userInfo["data"] as? String {
let data = dataString.data(using: .utf8)!
do {
if let json = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as? [String : Any]
{
let message = json["message"] as? String ?? "No message here"
let title = json["title"] as String ?? ""
//here is the problem..I have no idea to do it here
let payload = json["payload"] as? [String : Int] ?? [:]
for element in payload {
if let postId = element["post_id"] {
//print("postId = \(postId)")
}
}
} else {
print("bad json")
}
} catch let error as NSError {
print(error)
}
So as shown in above,I have no problem to get value of title,message and timestamp inside the data json.
But I have to idea how to get the value of post_id which is inside payload array.
So in this case,how to get the value of post_id from the data json above? Thanks.
Access post id like this
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
if let data = userInfo["data"] as? [String: Any],
let payload = data["payload"] as? [String: Any],
let postId = payload["post_id"] as? String{
print("post id \(postId)")
}else{
print("there is no post id inside the payload")
}
}

The JSON output does not contain a key: "value"

I have a JSON parsing issue with my Swift code below. The error I am getting says that my JSON output does not contain a key value.
My code:
Alamofire.request(url, method: .get, headers: headers).responseJSON { (response) -> Void in
let jsonValue = response.result.value as! NSDictionary
if let bpArray = jsonValue["value"] as? [NSDictionary]{
for results in bpArray {...}
Issue:
This conversion doesnt work: if let bpArray = jsonValue["value"] as? [NSDictionary]
My JSON Structure:
{
d: {
results: [
{
__metadata: {},
Key: "AFBWhULFHtKU4j4FhWCmKg==",
ParentKey: "AAAAAAAAAAAAAAAAAAAAAA==",
RootKey: "AFBWhULFHtKU4j4FhWCmKg==",
Partner: "MM-CARR-01",
Type: "2",
Description: "MM Demo Carrier Created for Single Stop / MA",
FrieghtOrder: {}
},
...
Assuming you want to access the results key so try like this:-
if let bpArray = jsonValue["results"] as? [String: AnyObject]{
//yourcode
}
Well your json structure haven't got any key named as value and that's why it's giving an error.
In order to get results array, you first need to get the object in which they are nested and for example 'g' in your case:
if let data = jsonValue["d"] as? [NSDictionary]{
if let resultsArray = data["results"] as? NSArray {
//your code
}
}
Please Use Swifty Json Pod And Try this code
pod 'SwiftyJSON'
In Your file where you get response
import SwiftyJSON
Then After Use This Code
switch response.result {
case .success(let JSON2):
print("Success with JSON: \(JSON2)")
// print("Request failed with error: \(response.response?.statusCode)")
if let response = JSON2 as? NSMutableDictionary
{
}
else if let response = JSON2 as? NSDictionary
{
if let data = response?.object(forKey: "d") as? NSDictionary
{
if let resultsArray = data?.object(forKey: "results") as? NSArray
{
}
}
}
else if JSON2 is NSArray
{
let swjson = JSON(response.result.value!)
print(swjson)
// callback(swjson,nil)
var myMutableDictionary = [AnyHashable: Any]()
myMutableDictionary["myArray"] = swjson
callback(myMutableDictionary as NSDictionary?,nil)
print("accc")
}
else if ((JSON2 as? String) != nil)
{
let userDic : [String : String] = ["quatid":JSON2 as! String]
print(userDic)
}
break
case .failure(let error):
print("Request failed with error: \(error)")
}
Remember it's better we not use NSArray & NSDictionary like things in SWIFT, SWIFT it self providing let, var keyword for various data type.
First you can create your model where you can save the data.
MyModel.swift
class MyModel: NSObject {
var ParentKey : Int?
init(jsonObject:[String:Any]) {
ParentKey = jsonObject["ParentKey"] as? String ?? ""
}
}
Viewcontroller.Swift
var myModel : [MyModel] = []
if let responseData = response["d"] as? [String:Any]{
if let dataObject = responseData["results"] as? [[String:Any]]{
self.myModel = dataObject.map({return MyModel(jsonObject: $0)})//for assigning data into model
}
}
As most people said, I was wrong with "value". Hussain's answer to using [String:AnyObject] Helped.
I am not sure if the below is neat to achieve, but it did the magic. App loaded as expected. Code expert below:
Solution:
if let bpData = jsonValue["d"] as? [String: AnyObject]{
for results in bpData {
let arrayInterim = results.value as? NSArray
for i in 0 ..< arrayInterim!.count {

Swift 3 HTTP Request post with parameter error JSON format

I'm trying to send a http request using swift 3
it started like this with 2.3 and it worked well
func addBill(){
let parameter:[String:AnyObject] =
[
"app":"mpbid",
"token":userDefault.getToken()!,
"ver":1,
"data":
[
[
"productId":String(self.product!.productId!),
"customerId":self.nomorTeleponField.text!
]
]
]
HTTPRequest.addBill(parameter, startRequest: {
}) { (responseType, message, data) in
if responseType == HTTPRequest.responseType.Success{
if let status = data!["status"] as? String where status == "OK"{
if let datas = data!["data"] as? NSArray where datas.count > 0{
let errorResponse = datas[0]["errorStatus"] as! String
(errorResponse.characters.count) ")
if errorResponse.characters.count == 0 {
self.inquiryData = datas[0] as? [String:AnyObject]
self.performSegueWithIdentifier("showConfirmation", sender: self)
it succeed with a status 200 OK
but after swift 3 migration, i've turned the source code to this
func addBill(){
let parameter:[String:AnyObject] =
[
"app":"mpbid" as AnyObject,
"token":userDefault.getToken()! as AnyObject,
"ver":1 as AnyObject,
"data":
[
[
"productId":String(describing: self.product!.productId!),
"customerId":self.nomorTeleponField.text!,
"productCode":String(describing: self.product!.productCode!)
],
] as AnyObject,
]
HTTPRequest.addBill(parameter, startRequest: {
}) { (responseType, message, data) in
if responseType == HTTPRequest.responseType.success{
if let status = data!["status"] as? String, status == "OK"{
if let datas = data!["data"] as? NSArray, datas.count > 0{
let errorResponse = (datas[0] as! [String:AnyObject])["errorStatus"] as! String(errorResponse.characters.count) ")
if errorResponse.characters.count == 0 {
self.inquiryData = datas[0] as? [String:AnyObject]
self.performSegue(withIdentifier: "showConfirmation", sender: self)
It gave me status 500 internal server error
I guess I got wrong JSON format on sending the parameter using swift 3, any help would be really appreciated... thanks before

TableView Json Swift

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 :
{
"0":
{
"id":"30",
"title":"galaxys6",
"price":"550",
"description":"neuf",
"addedDate":"2015-07-16 15:04:24",
"user_id":"2",
"user_name":"",
"user_zipCode":"69003",
"category_id":"1",
"category_label":"PHONE",
"subcategory_id":"1",
"subcategory_label":"Phone",
"picture":"",
"bdd":{},
"picture_url":"http:\/\/jdl-barreme-orange.dyndns.org\/WEBSERVICE\/pictures\/galaxy s6.JPG"
},
"1":
{
"id":"31",
"title":"iphone4",
"price":"570",
"description":"neuf",
"addedDate":"2015-07-16 15:14:54",
"user_id":"2",
"user_name":"",
"user_zipCode":"69003",
"category_id":"1",
"category_label":"PHONE",
"subcategory_id":"1",
"subcategory_label":"Phone",
"picture":"",
"bdd":{},
"picture_url":"http:\/\/jdl-barreme-orange.dyndns.org\/WEBSERVICE\/pictures\/iphone.JPG"
},
}
For each object my webservice create a dictionary (0;1;2;3....)
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 jsonData:NSDictionary = NSJSONSerialization.JSONObjectWithData(urlData!, options:NSJSONReadingOptions.MutableContainers , error: &error) as? NSDictionary{
// 4
if let resp = jsonData["1"] as? [NSDictionary] {
NSLog("%#", resp)
// 5
for item in resp {
repositories.append(Repository(jsonData: item))
}
repository controller :
class Repository {
var name: String?
var description: String?
var html_url: String?
init(jsonData: NSDictionary) {
self.name = jsonData["id"] as? String
self.description = jsonData["description"] as? String
self.html_url = jsonData["title"] as? String
}
}
But it doesn't work, I put a breakpoint, and xcode stop to interpret here :
if let resp = jsonData["1"] as? [NSDictionary] {
NSLog("%#", resp)
What am I doing wrong?
Thank you.
Here's how to get the title and price for your JSON:
if let json = NSJSONSerialization.JSONObjectWithData(urlData!, options: nil, error: nil) as? [String:AnyObject] {
for (_, value) in json {
if let dict = value as? [String:AnyObject] {
if let title = dict["title"] as? String {
println(title)
}
if let price = dict["price"] as? String {
println(price)
}
}
}
}
This can also be used to init your Repository classes if you want:
class Repository {
var name: String?
var description: String?
var html_url: String?
init(jsonData: [String:AnyObject]) {
self.name = jsonData["id"] as? String
self.description = jsonData["description"] as? String
self.html_url = jsonData["title"] as? String
}
}
var repos = [Repository]()
if let json = NSJSONSerialization.JSONObjectWithData(urlData!, options: nil, error: nil) as? [String:AnyObject] {
for (_, value) in json {
if let dict = value as? [String:AnyObject] {
let repo = Repository(jsonData: dict)
repos.append(repo)
}
}
}
for repo in repos {
println(repo.name)
println(repo.description)
println(repo.html_url)
}
In the loop I'm ignoring the key: for (_, value) in json but you can use it if needed of course:
for (key, value) in json {
println(key) // "1", "2", ...
// ...
}
UPDATE:
Following your comment asking how to use this answer if your data format is different: if you want an array of dictionaries, change the typecast of the NSJSONSerialization result to reflect that: [[String:AnyObject]]. Next you can iterate over your array to get each dictionary properties:
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)
}
}
}
You are making a mistake here
if let resp = jsonData["1"] as? [NSDictionary]
This should be a NSDictionary not [NSDictionary], (which would be an array of dictionaries).
Also this conditional block
if let reposArray = jsonData["items"] as? [NSDictionary]
will never be executed because jsonData does not contain a key "items".
I guess it is the [NSDictionary]
if let resp = jsonData["1"] as? [NSDictionary]
[NSDictionary] is array of NSDictionary same as Array<NSDictionary>
just remove the brackets [] and change to
if let resp = jsonData["1"] as? NSDictionary