How to store NSArray in Userdefaults? - json

Here is my code
var defaultValues = UserDefaults.standard
var json = NSArray()
self.defaultValues.set(json, forKey: "BedData")
I used this Code to store Strings and it works perfectly but when i tried to store NSArray it gives me this error "Attempt to insert non-property list object"

You have to encode and decode for adding and retrieving data to/from UserDefault.
func getUserDetail() -> UserDetail? {
if let decodedData = UserDefaults.standard.object(forKey: AppConstant.userDefaultKey.user_detail) as? Data {
return try! PropertyListDecoder().decode(UserDetail.self, from: decodedData)
}
return nil
}
func setUserDetail(user: UserDetail) {
UserDefaults.standard.set(try! PropertyListEncoder().encode(user), forKey: AppConstant.userDefaultKey.user_detail)
}

Thanks for the replies Guys But i have found the solution
Let json = NSArray()
To Store
let data = NSKeyedArchiver.archivedData(withRootObject: json)
self.defaultValues.set(data, forKey: "Offline-BedData")
And to Retrieve:
if let data = self.defaultValues.object(forKey: "Offline-BedData")! as? Data {
if let dict = NSKeyedUnarchiver.unarchiveObject(with: data) as? NSArray {
json = dict
print("json\(json)")
self.performSegue(withIdentifier: "BedShow", sender: Any?.self)
}
}

Related

How do I get my Swift code to read a specific piece of information from the JSON file

I am trying to read the data for "Name" in a JSON file I am hosting using Swift and I seem to only be able to read the whole JSON file and not able to pick out specific data. My JSON file contains this:
[{"Email":"Admin#admin.com","Password":"password","Name":"Admin"}]
The swift code I am using is this:
override func viewDidLoad() {
super.viewDidLoad()
//to get data from external DB
let url = URL(string: "http://localhost/Projects/Test_mobileAPI/test_userInfo.php?email=Admin#admin.com")
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error != nil{
print("Error Occured")
}
else{
print("Okie")
if let content = data {
do{
//Array
let myJson = try JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject
print("this part works")
print(myJson)
if let diction = myJson as? NSDictionary
{
if let name = myJson["Name"]{
print(name as Any)
}
}
}
catch{
print(error)
}
}
}
}
task.resume()
}
The output I keep getting is this:
Okie
this part works
(
{
Email = "Admin#admin.com";
Name = Admin;
Password = password;
}
)
But I do not get just the value for "Name". Can anyone help me get the value for "Name" (i.e "Admin")
Can you try
if let myJson = try JSONSerialization.jsonObject(with: content) as? [[String:Any]] {
if let first = myJson.first {
print(first["Name"])
}
}
The problem is that the JSON that you're receiving back isn't a Dictionary, it's a single element array with a dictionary in it. So when you do
if let diction = myJson as? NSDictionary
the myJson object is failing the cast to NSDictionary. If you unwrap the array first, you should then be able to reference the dictionary and pick off any keyed values you want:
if let array = myJson as? NSArray
{
if let myDict = array[0] as? NSDictionary
{
if let name = myDict ["Name"]{
print(name as Any)
}
}
}

Trouble getting data from TheMovieDB API with Swift JSON

I am brand new to using JSON and wanted to get started with a simple app to provide a movie overview when you type in a title. My below code returns everything in one big string. How do I get just one piece of information like the overview or year?
With my below attempt, print(obj["overview"] as Any)) prints "nil" and print(obj) looks like this:
{
page = 1;
results = (
{
adult = 0;
"backdrop_path" = "/A0aGxrCGRBuCrDltGYiKGeAUect.jpg";
"genre_ids" = (
53,
80
);
id = 680;
"original_language" = en;
"original_title" = "Pulp Fiction";
overview = "A burger-loving hit man, his philosophical partner, a drug-addled gangster's moll and a washed-up boxer converge in this sprawling, comedic crime caper. Their adventures unfurl in three stories that ingeniously trip back and forth in time.";
Current Code:
let query = "Pulp+Fiction"
let urlString = "https://api.themoviedb.org/3/search/movie?api_key={MYAPIKEY}&query=\(query)"
let url = URL(string: urlString)
URLSession.shared.dataTask(with:url!) { (data, response, error) in
if error != nil {
print(error as Any)
} else {
do {
let parsedData = try JSONSerialization.jsonObject(with: data!) as Any
if let obj = parsedData as? NSDictionary {
print(obj["overview"] as Any)
print(obj)
}
} catch {
print("error")
} }
}.resume()
}
// write this extension anywhere in your any swift file
extension String{
func toDictionary() -> NSDictionary {
let blankDict : NSDictionary = [:]
if let data = self.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as! NSDictionary
} catch {
print(error.localizedDescription)
}
}
return blankDict
}
}
//now in your code modify as
if data != nil {
let responseString = String(data: data!, encoding: .utf8)!
if(responseString != "")
{
//convert response string into dictionary using extended method
let responseValues = responseString.toDictionary()
//access value using keyPath using
let value = responseValues.value(forKeyPath: "key.key2")
//where key2 is the target key which is inside the value of key
}
}
First of all JSON results are never Any. As already mentioned in the comments the root object is a dictionary
if let parsedData = try JSONSerialization.jsonObject(with: data!) as? [String:Any],
The key overview is in array for key results
let results = parsedData["results"] as? [[String:Any]] {
You have to iterate over the array to get the values for key overview
for result in results {
print(result["overview"] as? String ?? "no value for key overview")
}
}
It's highly recommended to use the Codable protocol and custom structs in Swift 4.

How to get the multiple data inside the json curly braces? Swift

How to get the multiple data inside the json curly braces in swift3?
Can i use this code to get multiple data? (get "crew_id","crew_name","crew_email")
if let crew = user!["crew"] as? [String:Any], let crewName = crew["crew_name"] as? String {
print(crewName)
JSON
crew ={
"crew_avatar" = "http://ec2-52-221-231-3.ap-southeast-1.compute.amazonaws.com/gv/images/profile_image/Pang_Kang_Ming_916210_0e9.jpg";
"crew_contact" = 0123456789;
"crew_email" = "pang#xover.com.my";
"crew_gender" = Male;
"crew_id" = PP000001;
"crew_name" = "Pang Kang Ming";
"crew_preferred_name" = PKM;
"crew_qrcode" = "images/qrcode/qrcode_085960293a5378a64bec6ebfa3c89bb7.png";
};
message = "Login Sucessfully";
result = success;
Yes you can, just add the values you want to unwrap as below, just be aware that if one of the optional binding does not unwrap, even if others unwrap if statement will not be executed, consider separating the if statements.
Depends on all being returned in the json.
if let crew = user!["crew"] as? [String:Any],
let crewName = crew["crew_name"] as? String,
let crewId = crew["crew_id"] as? String {
print(crewName)
print(crewId)
}
Recommended way, even if some values are not present in the json response, you will be able to get the other values.
if let crew = user!["crew"] as? [String:Any] {
if let crewName = crew["crew_name"] as? String {
print(crewName)
}
if let crewId = crew["crew_id"] as? String {
print(crewId)
}
}
if let file = Bundle.main.url(forResource: "yourJsonFileName", withExtension: "json") {
let data = try Data(contentsOf: file)
let json = try JSONSerialization.jsonObject(with: data, options: [])
let jsonData = json as! [[String:Any]]
DispatchQueue.main.async {
let projectName = jsonData.flatMap { $0["crew_avatar"] as? String }
self.crewAvatarArray = projectName
print(self.crewAvatarArray)
let subTitle = jsonData.flatMap { $0["crew_contact"] as? String }
self.crewContactArray = subTitle
let startDate = jsonData.flatMap { $0["crew_email"] as? String }
self.crewEmailArray = startDate
}
}
Try this code

Swift JSONSerialization.jsonObject Error

I've looked around but I don't find an answer to fix this error that has been bugging me. I tried adding a "as! NSMutableArray" but that gave me another error. Any ideas on how to fix it? I converted my project from Objective-C to Swift, so hopefully the code is all good I had 20+ errors now I'm down to 3 errors. Thank you.
Error Message:
'jsonObject' produces 'Any', not the expected contextual result type 'NSMutableArray'
Code for retrieving data from server
// Retrieving Data from Server
func retrieveData() {
let getDataURL = "http://ip/example.org/json.php"
let url: NSURL = NSURL(string: getDataURL)!
do {
let data: NSData = try NSData(contentsOf: url as URL)
jsonArray = JSONSerialization.jsonObject(with: data, options: nil)
}
catch {
print("Error: (data: contentsOf: url)")
}
// Setting up dataArray
var dataArray: NSMutableArray = []
// Looping through jsonArray
for i in 0..<jsonArray.count {
// Create Data Object
let dID: String = (jsonArray[i] as AnyObject).object(forKey: "id") as! String
let dName: String = (jsonArray[i] as AnyObject).object(forKey: "dataName") as! String
let dStatus1: String = (jsonArray[i] as AnyObject).object(forKey: "dataStatus1") as! String
let dStatus2: String = (jsonArray[i] as AnyObject).object(forKey: "dataStatus2") as! String
let dURL: String = (jsonArray[i] as AnyObject).object(forKey: "dataURL") as! String
// Add Data Objects to Data Array
dataArray.add(Data(dataName: dName, andDataStatus1: dStatus1, andDataStatus2: dStatus2, andDataURL: dURL, andDataID: dID))
}
self.myTableView.reloadData()
}
The jsonObject function will return a value of type Any but the jsonArray's type of NSMutableArray. And this function will throw an error if something is wrong, put a try keyword before it. In my experience, let change the type of jsonArray to array of dictionary, so you will extract data with ease.
do {
let data: Data = try Data(contentsOf: url as URL)
let jsonArray: [[String: AnyObject]] = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! [[String: AnyObject]]
print("json: \(jsonArray)")
for dict in jsonArray {
let dataName = dict["dataName"] as! String
print("dataName: \(dataName)")
}
}
catch {
print("Error: (data: contentsOf: url)")
}

How do I get a specific value from returned json in Swift 3.0?

I am trying to get a value from json in Swift. I have added an image of the data tree. My previous attempts have not worked. Below is code which prints the full json object which is what I don't want.
json tree image
import PlaygroundSupport
import UIKit
let url = URL(string: "https://api.data.gov.sg/v1/transport/taxi-availability")
var request = URLRequest(url: url!);
request.addValue("xxxx", forHTTPHeaderField: "api-key")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard error == nil else {
print(error)
return
}
guard let data = data else {
print("Data is empty")
return
}
let json = try! JSONSerialization.jsonObject(with: data, options: [])
//print(json)
}//end
//["features"]??[0]?
task.resume()
PlaygroundPage.current.needsIndefiniteExecution = true
You just need to do something with the json you've been vended:
let task = URLSession ... { data, response, error in
let json = JSONSerialization.jsonObject(...)
if let json = json as? [String: Any] {
// now you have a top-level json dictionary
for key, value in json {
print("json[\"\(key\")] = \(value)")
}
}
}
I didn't verify the following code but it should work for the son tree you provided. (disclaimer: might have some errors but its mostly correct)
if let json = (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String:Any]
, let features = json["features"] as? [Any]
, let firstFeature = features[0] as? [String:Any]
, let properties = firstFeature["properties"] as? [String:Any]
, let taxiCount = properties["taxi_count"] as? Int
{
print(taxiCount)
}
If Json is dictionary
let json = try! JSONSerialization.jsonObject(with: data, options: [])
let jsonDict = json as? NSDictionary
//if you have a key name
let name = jsonDict["name"] as? String
//and so on
//if you have a array in your dictionary
let likes = jsonDict["likes"] as? NSArray
let numberOfLikes = likes.count
for eachLike in likes {
let likerName = eachLike["liker_name"] as? String
}