Unable to convert json string to json object - ios

let dictionaryToJsonObject: [String: Any]
let Dictionary: [String: Any] = ["FirstName": "John", "Email": "Jo#sm.com", "Password": "john#123", "LastName": "Smith", "Organization": ["Type": 5, "Name": "IT"]]
do {
let jsonData = try JSONSerialization.data(withJSONObject: Dictionary as Any, options: .prettyPrinted)
let jsonText = String(data: jsonData,
encoding: .ascii)
print("JSON string = \(jsonText!)")
if JSONSerialization.isValidJSONObject(jsonText!) {
print("Valid")
} else {
print("Not Valid")
}
}catch {
print(error.localizedDescription)
}
Output Will be : -
JSON string = {
"FirstName" : "John",
"Email" : "Jo#sm.com",
"Password" : "john#123",
"LastName" : "Smith",
"Organization" : {
"Type" : 5,
"Name" : "IT"
}
}
expected Result :
{
FirstName:"John",
Email:"Jo#sm.com",
Password:"john#123",
LastName:"Smith",
Organization:{
Type:5,
Name:"IT"
}
}

If you want to get it in json object form then your code should be like,
let dictionaryToJsonObject: [String: Any]
let Dictionary: [String: Any] = ["FirstName": "John", "Email": "Jo#sm.com", "Password": "john#123", "LastName": "Smith", "Organization": ["Type": 5, "Name": "IT"]]
do {
let jsonData = try JSONSerialization.data(withJSONObject: Dictionary as Any, options: .prettyPrinted)
let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: .init(rawValue: 0))
print("JSON string = \(jsonObject)")
if JSONSerialization.isValidJSONObject(jsonObject) {
print("Valid")
} else {
print("Not Valid")
}
}catch {
print(error.localizedDescription)
}
and your output will be,
JSON string = {
Email = "Jo#sm.com";
FirstName = John;
LastName = Smith;
Organization = {
Name = IT;
Type = 5;
};
Password = "john#123";
}
Valid
Ultimately it is your declared dictionary itself I think!

Related

Decode JSON that has dynamic key

I have response that looks like below JSON. The problem is I have dynamic key which is hashed. I am pretty lost in creating a Decodable struct for this response.
I have tried below code but it fails with data mismatch because of planName got introduced recently.
struct ProductDescriptionResponse {
let disclaimersHtml: String?
let additionalProperties: [String: ProductDescription]?
}
struct ProductDescription {
var disclaimersHtml: String?
var hasPlanDetailsV2: Bool?
let planDescription: String
let serviceDescriptions: [ServiceDescriptions]
}
struct ServiceDescriptions {
let name: String
let subTitle: String?
let icon: String?
let description: String?
let upgradeText: String?
let featureDisclaimer: String?
}
func productDescriptions() -> Observable<ProductDescriptionResponse> {
return APIClient.sharedInstance.rx.response(apiURL: APIURL.productDescription, requestType: .get, httpBody: nil, header: .auth).map({ (responseData) -> ProductDescriptionResponse in
var parsedData = try JSONSerialization.jsonObject(with: responseData) as? [String:Any]
// Remove disclaimersHtml key from responseData & hold it to pass
// in ProductDescriptionResponse constructor during return.
let disclaimersHtml = parsedData?.removeValue(forKey: "disclaimersHtml") as? String
// Product descriptions.
var productDescriptions: [String: ProductDescription]? = nil
if let parsedData = parsedData {
// Json data without disclaimersHtml.
let jsonData = try JSONSerialization.data(withJSONObject: parsedData, options: .prettyPrinted)
productDescriptions = try JSONDecoder().decode([String: ProductDescription].self, from: jsonData)
}
// ProductDescriptionResponse with disclaimersHtml & productDescriptions.
return ProductDescriptionResponse(disclaimersHtml: disclaimersHtml,
additionalProperties: productDescriptions)
})
}
JSON Response:
{
"disclaimersHtml": "",
"planName": "",
“abc456753234”: {
"planDescription": "",
"hasPlanDetailsV2": false,
"serviceDescriptions": [
{
"name": "",
"subTitle": "",
"icon": "",
"hasTile": "",
"tileTitle": "",
"description": "",
"featureDisclaimer": "",
"upgradeText": ""
},
{
"name": "",
"subTitle": "",
"icon": "",
"hasTile": "",
"tileTitle": "",
"description": "",
"featureDisclaimer": "",
"upgradeText": ""
}
]
},
“xyz123456789”: {
"planDescription": "",
"hasPlanDetailsV2": true,
"serviceDescriptions": [
{
"name": "",
"subTitle": "",
"icon": "",
"hasTile": "",
"tileTitle": "",
"description": "",
"featureDisclaimer": "",
"upgradeText": ""
}
]
}
}
If I do below, it works. But don't want to keep on hardcoding like this:
let _ = parsedData?.removeValue(forKey: "planName") as? String
Is there any better for this type of JSON to get working? I don't want to hardcode and keep stripping of values to get ProductDescriptionResponse because this field can get added in future.
I would solve this problem using CustomCodingKeys:
struct ProductDescriptionResponse: Decodable {
let disclaimersHtml: String?
let additionalProperties: [String: ProductDescription]?
var disclaimersHtml: String? = nil
var additionalProperties: [String: ProductDescription]? = nil
private struct CustomCodingKeys: CodingKey {
var stringValue: String
init?(stringValue: String) {
self.stringValue = stringValue
}
var intValue: Int?
init?(intValue: Int) {
return nil
}
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CustomCodingKeys.self)
self.additionalProperties = [String: ProductDescription]()
for key in container.allKeys {
do {
if let keyValue = CustomCodingKeys(stringValue: key.stringValue) {
if keyValue.stringValue == "disclaimersHtml" {
self.disclaimersHtml = try container.decodeIfPresent(String.self, forKey: keyValue)
}
self.additionalProperties?[keyValue.stringValue] = try container.decodeIfPresent(ProductDescription.self, forKey: keyValue)
}
} catch {
// Silently ignore the error
}
}
}
}
func productDescriptions() -> Observable<ProductDescriptionResponse> {
return APIClient.sharedInstance.rx.response(memberAPIURL: MemberAPIURL.productDescription, requestType: .get, httpBody: nil, header: .auth).map({ (response) -> ProductDescriptionResponse in
return try JSONDecoder().decode(ProductDescriptionResponse.self, from: response)
})
}
The way I solved is iterate through (key, value) of serialized JSON.
Check value is of type Dictionary<AnyHashable,Any> and decode only if that matches, else ignore.
func productDescriptions() -> Observable<ProductDescriptionResponse> {
return APIClient.sharedInstance.rx.response(memberAPIURL: MemberAPIURL.productDescription, requestType: .get, httpBody: nil, header: .auth).map({ (responseData) -> ProductDescriptionResponse in
var productDescriptionResponse = ProductDescriptionResponse(disclaimersHtml: nil, additionalProperties: nil)
var additionalParams: [String: ProductDescription] = [:]
do {
productDescriptionResponse = try JSONDecoder().decode(ProductDescriptionResponse.self, from: responseData)
if let jsonObject = try JSONSerialization.jsonObject(with: responseData, options: .mutableLeaves) as? [String : Any] {
for (key,value) in jsonObject {
if value is Dictionary<AnyHashable,Any> {
let jsonData = try JSONSerialization.data(withJSONObject: value, options: JSONSerialization.WritingOptions.prettyPrinted)
let productDescription = try JSONDecoder().decode(ProductDescription.self, from: jsonData)
additionalParams[key] = productDescription
}
}
productDescriptionResponse.additionalProperties = additionalParams
}
} catch {
// handle error
}
return productDescriptionResponse
})
}

Parsing json string crashes

I'm trying to parse a json string:
if let jsonStr = asd.value(forKey: "orderData") as? String {
print(jsonStr)
let data = jsonStr.data(using: String.Encoding.utf8, allowLossyConversion: false)!
do {
let json = try JSONSerialization.jsonObject(with: data, options: []) as! [String: AnyObject] // CRASHES HERE
if let names = json["product_name"] as? [String] {
print(names)
}
} catch let error as NSError {
print("Failed to load: \(error.localizedDescription)")
}
}
But at the line let json = try JSONSeri... it crashes saying Could not cast value of type '__NSArrayI' to 'NSDictionary'.
Also tried changing this as! [String: AnyObject] to as! [[String: AnyObject]]. But it still doesn't work.
This is my json string structure:
[
{
"product_id" : "1",
"category_json" : {
"category_id" : "1",
"category_name" : "nvm"
},
"selling_price" : "200",
"product_name" : "nvm",
},
{
"product_id" : "2",
"category_json" : {
"category_id" : "2",
"category_name" : "cas"
},
"selling_price" : "800",
"product_name" : "cas",
}
]
You should not be force casting with ! unless you are 100% sure that it will succeed.
I would suggest you use the following:
let jsonArray = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: Any]]
This will return you a list of products. If you want a list of the product names than you need to iterate over it and extract the product name of each item. You can do this like so:
let names = jsonArray.map({ $0["product_name"] as? String })
As already mentioned the object is an array, you have to use a for loop to get all items
...
let data = Data(jsonStr.utf8)
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [[String: Any]] {
for item in json {
if let name = item["product_name"] as? String {
print(name)
}
}
}
} catch {
print("Failed to load: \(error.localizedDescription)")
}

How to convert JSON String to JSON Object in swift?

I trying to generate JSON Object and convert that to JSON String and that process is Successfully placed. But my real problem rises when I try to convert JSON String to JSON Object. When I try I get nil as result.
func generateJSONObject() {
let jsonObject = createJSONObject(firstName: firstName[0], middleName: middleName[0], lastName: lastName[0], age: age[0], weight: weight[0])
print("jsonObject : \(jsonObject)")
let jsonString = jsonObject.description // convert It to JSON String
print("jsonString : \(jsonString)")
let jsonObjectFromString = convertToDictionary(text: jsonString)
print("jsonObjectFromString : \(String(describing: jsonObjectFromString))")
}
createJSONObject func
// JSON Object creation
func createJSONObject(firstName: String, middleName: String, lastName: String, age: Int, weight: Int) -> [String: Any] {
let jsonObject: [String: Any] = [
"user1": [
"first_name": firstName,
"middle_name": middleName,
"last_name": lastName,
"age": age,
"weight": weight
]
]
return jsonObject
}
convertToDictionary func
func convertToDictionary(text: String) -> [String: Any]? {
if let data = text.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
} catch {
print(error.localizedDescription)
}
}
return nil
}
Logs
When I print JSON Object I get
jsonObject : ["user1": ["age": 21, "middle_name": "Lazar", "last_name": "V", "weight": 67, "first_name": "Alwin"]]
When I print JSON String I get
jsonString : ["user1": ["age": 21, "middle_name": "Lazar", "last_name": "V", "weight": 67, "first_name": "Alwin"]]
Convert JSON String to JSON Object I get below error
The data couldn’t be read because it isn’t in the correct format.
jsonObjectFromString : nil
I don't know why this happening. I want to convert JSON String to JSON Object and I want to parse the JSON.
based on discussion
import Foundation
let firstName = "Joe"
let lastName = "Doe"
let middleName = "Mc."
let age = 100
let weight = 45
let jsonObject: [String: [String:Any]] = [
"user1": [
"first_name": firstName,
"middle_name": middleName,
"last_name": lastName,
"age": age,
"weight": weight
]
]
if let data = try? JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted),
let str = String(data: data, encoding: .utf8) {
print(str)
}
prints
{
"user1" : {
"age" : 100,
"middle_name" : "Mc.",
"last_name" : "Doe",
"weight" : 45,
"first_name" : "Joe"
}
}
Json has to be in Array or Dictionary, it can't be only string so to create a jsonstring first you need to convert to Data format and then convert to String
func generateJSONObject() {
let jsonObject = createJSONObject(firstName: "firstName", middleName: "middleName", lastName: "lastName", age: 21, weight: 82)
print("jsonObject : \(jsonObject)")
if let jsonString = convertToJsonString(json: jsonObject), let jsonObjectFromString = convertToDictionary(text: jsonString) {
print("jsonObjectFromString : \(jsonObjectFromString)")
}
}
func convertToJsonString(json: [String: Any]) -> String? {
do {
let jsonData = try JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)
return String(data: jsonData, encoding: .utf8)
} catch {
print(error.localizedDescription)
}
return nil
}

post data and get data from json url in swift?

I tried the below code for post and get data from json, in struck in getting data from json
http://beta.json-generator.com/api/json/get/EJoC6gB_z
[
{
"UserRole": "User",
"UserName": "Trinadh Reddy",
"Id": 15,
"Email": "trinadhvidavaluru#gmail.com"
},
{
"UserRole": "User",
"UserName": "fayaz sk",
"Id": 16,
"Email": "fayaz.net717#gmail.com"
},
{
"UserRole": "NewUser",
"UserName": "Gowtham M",
"Id": 17,
"Email": "mgowtham666#gmail.com"
},
{
"UserRole": "User",
"UserName": "fayaz sk",
"Id": 18,
"Email": "fayaz8484#gmail.com"
},
{
"UserRole": "NewUser",
"UserName": null,
"Id": 19,
"Email": null
},
{
"UserRole": "User",
"UserName": null,
"Id": 20,
"Email": null
},
{
"UserRole": "NewUser",
"UserName": "Fayaz Shaik",
"Id": 21,
"Email": "fayaz717#gmail.com"
},
{
"UserRole": "NewUser",
"UserName": "Trinadh Reddy",
"Id": 22,
"Email": "trinadh.engineer#gmail.com"
},
{
"UserRole": "NewUser",
"UserName": "tarun gandham",
"Id": 23,
"Email": "gandham.tarun#gmail.com"
},
{
"UserRole": "NewUser",
"UserName": null,
"Id": 24,
"Email": "admin#gmail.com"
},
{
"UserRole": "NewUser",
"UserName": "John",
"Id": 25,
"Email": "john#gmail.com"
},
{
"UserRole": "NewUser",
"UserName": "venkatesh kakumani",
"Id": 26,
"Email": "veenkys01#gmail.com"
}
]
code:
let givenName = user.profile.name
let email = user.profile.email
let param=["UserName":givenName!,"Email":email!] as Dictionary<String,String>
let request = NSMutableURLRequest(url: NSURL(string:"http://sstarapiservice.azurewebsites.net/api/users/")! as URL)
let session = URLSession.shared
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.httpBody = try! JSONSerialization.data(withJSONObject: param, options: [])
let task = session.dataTask(with: request as URLRequest) { data, response, error in
guard data != nil else {
print("no data found: \(error)")
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary {
print("Response: \(json)")
if var role = json["UserRole"] as AnyObject? as! String?
{
print("assigned Role= \(role)")
if role == "User"{
print("App permissions approved")
let myStoryBoard:UIStoryboard = UIStoryboard(name:"Main",bundle:nil)
let page=myStoryBoard.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
let pageNav = UINavigationController(rootViewController:page)
let appDelegate:AppDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController=pageNav
self.window?.rootViewController=pageNav
//self.window?.rootViewController = page
}
else{
print("wait for Approval...")
let myStoryBoard:UIStoryboard = UIStoryboard(name:"Main",bundle:nil)
let page=myStoryBoard.instantiateViewController(withIdentifier: "ApprovalUser") as! HomeViewController
let pageNav = UINavigationController(rootViewController:page)
let appDelegate:AppDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController=pageNav
self.window?.rootViewController=pageNav
// let myStoryBoard:UIStoryboard = UIStoryboard(name:"Main",bundle:nil)
// let page=myStoryBoard.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
// let pageNav = UINavigationController(rootViewController:page)
// let appDelegate:AppDelegate = UIApplication.shared.delegate as! AppDelegate
// appDelegate.window?.rootViewController=pageNav
// self.window?.rootViewController=pageNav
//self.window?.rootViewController = page
}
}
//
}
else {
var jsonStr = " "
var jsonDictionary = [String: Any]()
jsonStr = NSString(data: data!, encoding: String.Encoding.utf8.rawValue) as! String
print("Error could not parse JSON: \(jsonStr)")
print("121")
if var role = jsonStr as String?{
print("role= \(role)")
}
var role = JSONDict["UserRole"] as AnyObject? as! String?
print("success = \(role)")
// if var role = jsonDictionary["UserRole"] as! String?
// {
// print("role is:\(role)")
// }
let myStoryBoard:UIStoryboard = UIStoryboard(name:"Main",bundle:nil)
let page=myStoryBoard.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
let pageNav = UINavigationController(rootViewController:page)
let appDelegate:AppDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController=pageNav
self.window?.rootViewController=pageNav
}
} catch let parseError {
print(parseError)// Log the error thrown by `JSONObjectWithData`
let jsonStr = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("Error could not parse JSON: '\(jsonStr)'")
print("12")
}
}
task.resume()
Request JSON data from Webservice APi in Swift 3
Here i have added two types of Methods by Using Alamofire or URLSession : -
import UIKit
import Alamofire
class ViewController: UIViewController {
let urlString = "http://beta.json-generator.com/api/json/get/EJoC6gB_z"
override func viewDidLoad() {
super.viewDidLoad()
// Choose only one function here for calling webservice
getValueofUser()
//Or
getuserDetails()
}
//MARK: - By Using Alamofire
func getValueofUser(){
Alamofire.request(urlString, method: .get)
.responseJSON { response in
print("Success: \(response.result.isSuccess)")
switch response.result {
case .success:
self.successGetTermsData(response: response.result.value! as Any)
case .failure(let error):
print(error)
}
}
}
//MARK: - Or Use URLSession methods
func getuserDetails(){
let url = URL(string: urlString)
URLSession.shared.dataTask(with:url!) { (data, response, error) in
if error != nil {
print(error ?? "")
} else {
do {
let response = try JSONSerialization.jsonObject(with: data!, options: [])
self.successGetTermsData(response: response)
} catch let error as NSError {
print(error)
}
}
}.resume()
}
func successGetTermsData(response: Any){
let arrayOfDetails = response as? [[String: Any]] ?? []
// Do Something with the Array
//Here you will be get Array of User Related Details
let email = arrayOfDetails[0]["Email"] as? String ?? ""
let username = arrayOfDetails[0]["UserName"] as? String ?? ""
let Id = arrayOfDetails[0]["Id"] as? Int ?? 0
let UserRole = arrayOfDetails[0]["UserRole"] as? String ?? ""
print("Email ID -" ,email, "User Name -", username, "ID -",Id, "UserRole -", UserRole)
}
}
OutPut : -
Email ID - trinadhvidavaluru#gmail.com User Name - Trinadh Reddy ID - 15 UserRole - User

NSJSONSerialization return nil with a valid json

I try to parse a response which return a valid JSON with NSJSonSerialization. But it returns nil with no error. It works with another JSON response.
I did some search, and this could be a problem with the encoding of the JSON. I don't know how to solve it. Any idea ?
let url: NSURL = NSURL(string: urlPath)!
self.searchRequest = NSMutableURLRequest(URL: url)
if let searchRequest = self.searchRequest {
searchRequest.HTTPMethod = "GET"
let authString : String = SNCF.APIKey + ":" + ""
let authData : NSData = authString.dataUsingEncoding(NSASCIIStringEncoding)!
let authValue : String = "Basic " + authData.base64EncodedStringWithOptions(.EncodingEndLineWithCarriageReturn)
searchRequest.setValue(authValue, forHTTPHeaderField: "Authorization")
let queue:NSOperationQueue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(searchRequest, queue: queue, completionHandler:{ (response: NSURLResponse?, data: NSData?, error: NSError?) -> Void in
do {
//HERE JSONRESULT WILL BE NIL
if let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? [String: [AnyObject]] {
print("ASynchronous\(jsonResult)")
if let places = jsonResult["stop_areas"] as? [[String:AnyObject]]{
for placeDictionary in places {
if let labelText = placeDictionary["label"] as? String {
self.resultDatasource.append(labelText)
}
}
self.resultTableView.reloadData()
}
}
//HERE NO ERROR IS CATCHED
} catch let error as NSError {
print(error.localizedDescription)
}
})
Piece of my json response :
{
"disruptions": [],
"pagination": {
"start_page": 0,
"items_on_page": 100,
"items_per_page": 100,
"total_result": 3053
},
"stop_areas": [
{
"codes": [
{
"type": "CR-CI-CH",
"value": "0080-251967-BV"
}
],
"name": "gare de Perl",
"links": [],
"coord": {
"lat": "0",
"lon": "0"
},
"label": "gare de Perl",
"timezone": "Europe/Paris",
"id": "stop_area:OCE:SA:80251967"
},
{
...
},
//stop_areas dictionaries object...
], //end stop_areas array of dictionaries
"links": [
{
"href": "https://api.sncf.com/v1/coverage/sncf/stop_areas/{stop_areas.id}",
"type": "stop_areas",
"rel": "stop_areas",
"templated": true
},
{
"href": "https://api.sncf.com/v1/coverage/sncf/stop_areas?start_page=1",
"type": "next",
"templated": false
},
{
"href": "https://api.sncf.com/v1/coverage/sncf/stop_areas?start_page=30.52",
"type": "last",
"templated": false
},
{
"href": "https://api.sncf.com/v1/coverage/sncf/stop_areas",
"type": "first",
"templated": false
}
],
"feed_publishers": [
{
"url": "",
"id": "sncf",
"license": "",
"name": ""
}
]
}
The type of the JSON is [String: AnyObject] not [String: [AnyObject]]
I think this is the problem:
as? [String: [AnyObject]]
Try to remove the cast. If your JSON is correct and has no validation errors, the dictionary you get probably has the key value of type Any. You can try to use the dictionary by only casting the value keys you want:
if let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options: nil) {
print("ASynchronous\(jsonResult)")
if let places = jsonResult["stop_areas"] as? [[String:AnyObject]] {
...
}
}
Try This
do {
if let jsonResult: Dictionary = try NSJSONSerialization.JSONObjectWithData(self.mutableData, options: NSJSONReadingOptions.MutableContainers) as? Dictionary<String, AnyObject>
{
// print("get Read messages == \(jsonResult)");
if ((jsonResult["Warning"]) != nil)
{
let error_by_wc: NSString = jsonResult["Warning"] as! String
//print("results == \(error_by_wc)");
// printMessage("\(error_by_wc)")
JLToast.makeText("\(error_by_wc)").show()
}else if((jsonResult["Error"]) != nil)
{
let error_by_wc: NSString = jsonResult["Error"] as! String
// print("results == \(error_by_wc)");
// printMessage("\(error_by_wc)")
JLToast.makeText("\(error_by_wc)").show()
}
else
{
// read message s
}
} catch {
print(error)
}
If Data is Array Type Use this code
do {
if let jsonResult:NSArray = try NSJSONSerialization.JSONObjectWithData(self.mutableData, options: .MutableContainers) as? NSArray {
//print(jsonResult)
aDataBase.insertFromUserImage(jsonResult)
connection_allMEssages()
}else
{
//print("not data found")
BProgressHUD.dismissHUD(0)
}
} catch {
print(error)
BProgressHUD.dismissHUD(0)
}

Resources