Unable to get the value of JSON - Swift - ios

I tried to get the value of "seed" from json response. But i am getting nil.
Json Response:
{
"response": {
"params": {
"rows": "20",
"defType": "abc",
"seed": "381786611"
}
}
}
Swift Parsing:
if let responseHeader:AnyObject = object?["response"] as? NSDictionary {
if let t = (responseHeader["params"] as? NSDictionary){
let t1 = t["seed"] as? String
println("result is \(t1)") // This returns nil
}
}
Json Parsing
func processJsonToDictionary(object:AnyObject?) -> AnyObject?{
if object != nil {
if let data: AnyObject = object {
var parseError: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(object as NSData!, options: NSJSONReadingOptions.MutableContainers, error: &parseError) as? NSDictionary
if(parseError != nil){
return parseError
}
else{
return jsonResult
}
}
}
return nil
}
I am not able to get the value of t1. it always returns nil.
How can i get the value.
Also, I put a breakpoint and tried to print the value of t1. But the Xcode Keeps crashing. Why?

I think the major problem here is only accessing a JSON object in swift.
var error: NSError?
let jsonDict = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &error) as NSDictionary
let resp = jsonDict["response"] as? NSDictionary
let params = resp?["params"]?["seed"]
let seed = params!! as NSString
This is just to show you how a JSON object is accessed in swift. You can ofcourse change it according to your needs to remove unwanted Optional Chaining.

For easy JSON manipulation in Swift you could try this little library. It seems pretty easy and you could do this:
var dictionary: [String: AnyObject]!
if let json = NKJSON.parse(yourNSDataObject) {
dictionary <> json[NKJSON.rootKey]
}

First confirm that the response which you are getting is in json format or in string format.
For json parsing you can use swifty json pod

Related

How can I parse this JSON object using Swift 3.0

I'm trying to parse a JSON string returned from a new API. The returned JSON string looks like this.
QuerySearchResult":{
"StartAt":"1",
"Count":"40",
"TotalAvailable":"500",
"Items":[
{"TITLE":"OST420 Generation",
"PATH":"http:\\Test.pdf",
"WRITE":"2016-12-12T15:47:42",
"RANK":"32286574",
"SIZE":"145091",
"ISDOCUMENT":"true",
"ID":"18548",
"WPTASK":"Onsite Generation",
"WPDOCTYPE":"Local Operating Procedure",
"WPDOCREFID":"304580",
"WPCONTENTTYPE":"Document"},
{"TITLE":"OST420 Measurement",
"PATH":"http:\Test33.pdf",
.
.
I'm using the code below which accepts the JSON variable but fails when I try to load item. I've tried using Array around Dictionary but it still fails. What declaration do I need to read in Items?
if let json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as? Dictionary<String, AnyObject> {
for item in json {
if let dict = item as? Dictionary<String, AnyObject> {
if let items = json["Items"] as? Array<Dictionary<String, AnyObject>> {
for rec in items {
if let title = rec["TITLE"] as? String {
let xx = title
}
}
}
}
}
First of all you are not correctly iterating through Dictionary also instead of looping through Dictionary for accessing single value, try by directly accessing it through subscripting and the proper JSON notation of Dictionary in Swift 3 is [String : Any].
if let json = try? JSONSerialization.jsonObject(with: data!, options: []) as? [String : Any],
let queryDic = json["QuerySearchResult"] as? [String : Any],
let items = queryDic["Items"] as? [[String : Any]] {
for item in items {
if let title = item["TITLE"] as? String {
print(title)
}
}
}
In Swift 3.1 :-
func parseJson(anyObj:AnyObject) {
if let anyObj = anyObj as? Array<Dictionary<String,AnyObject>> {
self.yourArrayName = anyObj.flatMap({yourModelName(json:$0) })
}
}
The Json returns the data into the dictionary and array format, so treat the json data like it, it makes you easier to understand.
Data in braces '{' and '}' is dictionary.
and Data in braces '[' or ']' is array.
Now start parsing the json data by the dictionary and array properties it exactly works. Or for confirmation print your json data.
Use SwiftyJSON : which can simply and easily parse the JSON more than your code.
So, how do we parse using that?
First get your response as Data()
let jsonData = JSON(data: results!)
Then here how we parse that JSON.
import Foundation
import SwiftyJSON
enum JSONParseError : ErrorType {
case UnknownField
case EmptyJSON
}
extension JSONParseError : CustomStringConvertible {
var description: String {
switch self {
case .UnknownField:
return "Error when parsing json because there is no field"
case .EmptyJSON:
return "Error when parsing empty json"
}
}
}
guard let querySearchResult : [String : JSON] = jsonData["QuerySearchResult"].dictionary else{
throw JSONParseError.UnknownField
}
guard let startAt : String = querySearchResult["StartAt"].string else{
throw JSONParseError.UnknownField
}
guard let count : String = querySearchResult["Count"].string else{
throw JSONParseError.UnknownField
}
guard let totalAvailable : String = querySearchResult["TotalAvailable"].string else{
throw JSONParseError.UnknownField
}
guard let items : [JSON] = querySearchResult["Items"].array else{
throw JSONParseError.UnknownField
}
if items.count > 0 {
for i in 0 ..< items.count{
guard let title = items[i]["TITLE"].string else{
throw JSONParseError.UnknownField
}.... //So On
}
}else{
throw JSONParseError.EmptyJSON
}

Swift JSON error : Could not cast value of type '__NSDictionaryM' to 'NSArray'

when decoding JSON from webservice(API) i get error :
Could not cast value of type '__NSDictionaryM' (0x1037ad8a8) to 'NSArray' (0x1037ad470).
My Code :
var kGetURL = "http://bitnami.local/cscart_demo/api/users"
//var kGetURL = "http://localhost/fendy/getjson.php"
var json : Array<AnyObject> = []
override func viewDidLoad() {
super.viewDidLoad()
start()
}
func getData(data : NSData){
//error at this line :
json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! Array<AnyObject>
//error
tableView.reloadData()
}
func start(){
var url : NSURL = NSURL(string: kGetURL)!
var data : NSData = NSData(contentsOfURL: url)!
getData(data)
}
if i change url to http://localhost/fendy/getjson.php, its working so nice.
i get error if my url is http://bitnami.local/cscart_demo/api/users
Response from webservice http://localhost/fendy/getjson.php :
[{"id":"17","Name":"KFC","Message":"awesome"},
{"id":"18","Name":"McDonald","Message":"good"},
{"id":"23","Name":"Burger King","Message":"tasty"},
{"id":"38","Name":"Pizza hut","Message":"yummy"},
{"id":"39","Name":"Steak","Message":"very Delicious"}]
Response from webservice http://bitnami.local/cscart_demo/api/users :
{"users":
[{"user_id":"4","user_login":"user_4","is_root":"N","timestamp":"1441608048","user_type":"C","status":"A","firstname":"","lastname":"","email":"fendy.w#mvig.net","company":"","company_id":"1","company_name":"Simtech"},
{"user_id":"3","user_login":"customer","is_root":"N","timestamp":"1441604240","user_type":"C","status":"A","firstname":"Customer","lastname":"Customer","email":"customer#example.com","company":"Simtech","company_id":"1","company_name":"Simtech"},
{"user_id":"1","user_login":"admin","is_root":"Y","timestamp":"1441604240","user_type":"A","status":"A","firstname":"John","lastname":"Doe","email":"robby#mvig.net","company":"Your company","company_id":"0","company_name":null}],
"params":{"page":1,"items_per_page":"10","sort_order":"asc","sort_by":"name","sort_order_rev":"desc","total_items":"3"}}
i think it's Style is same, but why not working with url http://bitnami.local/cscart_demo/api/users . anyone can help?
The bitnami response starts with a { and it is therefore a JSON object, which corresponds to an NSDictionary. The other one starts with [ which indicates an array.
You need to change the type of json to Dictionary<String, AnyObject>, and deserialize as follows:
json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! Dictionary<String, AnyObject>
Your method is casting JSON result to an array. It works fine with the URL that returns an array represented as JSON, but it does not work with the URL that returns a dictionary, not an array, represented as JSON.
Although the "style" of returned values looks the same, the second one is a one-item dictionary. What you probably want is to extract the "users" element from it, which is an array.
If you do not know which of the two URLs you are getting, you could try both styles with as? cast instead of as!:
let tmp : AnyObject! = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil)
if let arr = tmp as? Array<AnyObject> {
json = arr
} else if dict = tmp as? [String: AnyObject] {
json = dict["users"] as! Array<AnyObject>
} else {
// Handle an error: the input was unexpected
}
tableView.reloadData()
try cache for Serialization
do {
if let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String : Any] { // as? data type
if let otherDict = json["dataKey"] as? [String : Any] {
//do something
}
}
} catch {
// can't json serialization
}

Cannot convert JSON to the correct format

I'd like to use JSON output from the public Web Service https://api.rbp-zp.cz/1.3/services/district/ but looks like there is a problem with encoding in this case.
AFNetworking use to do conversion in such cases (by specific respondSerializer) like this:
var op = AFHTTPRequestOperation (request: request)
op.responseSerializer = AFJSONResponseSerializer()
but it fails because of the invalid JSON structure.
I have tried to do conversion myself, but no outcome
let rObject: AnyObject? = NSJSONSerialization.JSONObjectWithData(decodedData, options:.AllowFragments, error: nil)
When I put manually this JSON from browser to validator http://jsonlint.com, then it says it is in incorrect format.
Strangely enough when I put the JSON message from my log into the validator then the structure is valid.
Any help would be appreciated.
func convertStringToDictionary(text: String) -> [String:String]? {
if let data = text.dataUsingEncoding(NSUTF8StringEncoding) {
var error: NSError?
let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: &error) as? [String:String]
if error != nil {
println(error)
}
return json
}
return nil
}
let str = "{\"name\":\"James\"}"
let result = convertStringToDictionary(str) // ["name": "James"]
if let name = result?["name"] { // The `?` is here because our `convertStringToDictionary` function returns an Optional
println(name) // "James"
}
In your version, you didn't pass the proper parameters to NSJSONSerialization and forgot to cast the result. Also, it's better to check for the possible error. Last note: this works only if your value is a String. If it could be another type, it would be better to declare the dictionary conversion like this:
let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: &error) as? [String:AnyObject]
and of course you would also need to change the return type of the function:
func convertStringToDictionary(text: String) -> [String:AnyObject]? { ... }
Ok, so workaround is trimming those funny characters in the end,..don't like it much but works
let range:NSRange = NSMakeRange(0, res.length - 3);
let refinedData:NSData = res.subdataWithRange(range)
let resObject = NSJSONSerialization.JSONObjectWithData(refinedData, options:NSJSONReadingOptions.allZeros, error: &error) as! NSArray
resObject is correctly filled as NSArray now

Check for http response format

I am making http call and receiving JSON response
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as! NSDictionary
But when not receiving actual json this line fail with error cannot cast value of NSArray to NSDictionary
I understand why this happen my question is how to properly check what format is the response
I do like this in my api's:
typealias JSONType = (dictionary: [String:AnyObject]?, array: [AnyObject]?)
var error:NSError?
var json:AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &error)
if let dict = json as? [String:AnyObject] {
return (dict, nil)
}
else if let arr = json as? [AnyObject] {
return (nil, arr)
}
So when I return that JSONType I can change to use it as a dictionary or array by just:
json.array

NSJSONSerialization.JSONObjectWithData Returns nil

[
{
"_id": "557f27522afb79ce0112e6ab",
"endereco": {
"cep": "asdasd",
"numero": "asdasd"
},
"categories": [],
"name": "teste",
"hashtag": "teste"
}
]
Returns nil without error :
var json = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.AllowFragments, error: &erro) as? NSDictionary
It's returning nil without error because it's not the JSON parsing that's failing. It's failing because of the conditional type cast of the resulting object as a dictionary. That JSON doesn't represent a dictionary: It's an array with one item (which happens to be a dictionary). The outer [ and ] indicate an array. So, when you parse this, you want to cast it as a NSArray.
For example, in Swift 1.2 you could:
if let json = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &error) as? NSArray, let dictionary = json.firstObject as? NSDictionary {
println(dictionary)
} else {
println(error)
}
Or you could cast it as an array of dictionaries:
if let json = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &error) as? [[String: AnyObject]], let dictionary = json.first {
println(dictionary)
} else {
println(error)
}
Calling isValidJSONObject: or attempting a conversion are the definitive ways to tell if a given object can be converted to JSON data.
isValidJSONObject(_:)
Returns a Boolean value that indicates whether a given object can be converted to JSON data.
Declaration
SWIFT
class func isValidJSONObject(_ obj: AnyObject) -> Bool
Parameters
obj
The object to test.
Return Value
true if obj can be converted to JSON data, otherwise false.
Discussion
Availability
Available in iOS 5.0 and later.

Resources