I have an object "itensList", it has the fields "name", "createdAt" and an array of "itens".
I want to be able to build JSON that looks like this:
{
"name": "List name"
"CreatedAt": "12:12 12/12/2016"
"itens": [
{
"title": "Item title"
"CreatedAt": "12:13 12/12/2016"
"isDone": false
},
{
"title": "Another item title"
"CreatedAt": "12:14 12/12/2016"
"isDone": true
}
]
}
I have tried a few different approaches with no success.
Item Object
class Item: Object {
dynamic var name = ""
dynamic var createdAt = NSDate()
dynamic var isDone = false
}
Item List Object
class ItemList: Object {
dynamic var name = ""
dynamic var createdAt = NSDate()
let itens = List<Item>()
}
For the example, let's make an object similar to what you must have:
class Iten {
let title:String
let createdAt:String
let isDone:Bool
init(title: String, createdAt: String, isDone: Bool) {
self.title = title
self.createdAt = createdAt
self.isDone = isDone
}
}
The trick I suggest is to add a computed value that will return a dictionary:
class Iten {
let title:String
let createdAt:String
let isDone:Bool
init(title: String, createdAt: String, isDone: Bool) {
self.title = title
self.createdAt = createdAt
self.isDone = isDone
}
var toDictionary: [String:AnyObject] {
return ["title": title, "createdAt": createdAt, "isDone": isDone]
}
}
Let's use it:
let iten1Dict = Iten(title: "title1", createdAt: "date1", isDone: false).toDictionary
let iten2Dict = Iten(title: "title2", createdAt: "date2", isDone: true).toDictionary
We now make the encapsulating dictionary:
let dict: [String:AnyObject] = ["name": "List name", "createdAt": "dateX", "itens": [iten1Dict, iten2Dict]]
To finish, we encode this dictionary to JSON data then we decode it as a String:
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(dict, options: .PrettyPrinted)
if let jsonString = String(data: jsonData, encoding: NSUTF8StringEncoding) {
print(jsonString)
}
} catch let error as NSError {
print(error)
}
And voilà:
{
"createdAt" : "dateX",
"itens" : [
{
"title" : "title1",
"createdAt" : "date1",
"isDone" : false
},
{
"title" : "title2",
"createdAt" : "date2",
"isDone" : true
}
],
"name" : "List name"
}
Raphael,
This piece of code builds a JSON query. It should get you started, just keep hacking and you'll find a way! That's the fun of programming!
func JSONquery()
let request = NSMutableURLRequest(URL: NSURL(string: "https://api.dropboxapi.com/2/files/get_metadata")!)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
request.addValue("application/json",forHTTPHeaderField: "Content-Type")
request.addValue("path", forHTTPHeaderField: lePath)
let cursor:NSDictionary? = ["path":lePath]
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(cursor!, options: [])
request.HTTPBody = jsonData
print("json ",jsonData)
} catch {
print("snafoo alert")
}
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
if let error = error {
completion(string: nil, error: error)
return
}
let strData = NSString(data: data!, encoding: NSUTF8StringEncoding)
//print("Body: \(strData)\n\n")
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers);
self.jsonPParser(jsonResult,field2file: "ignore")
/*for (key, value) in self.parsedJson {
print("key2 \(key) value2 \(value)")
}*/
completion(string: "", error: nil)
} catch {
completion(string: nil, error: error)
}
})
task.resume()
}
Like this:
var item = [
"title": "Item title",
"CreatedAt": "12:13 12/12/2016",
"isDone": false
]
var mainDictionary = [
"name": "List name",
"CreatedAt": "12:12 12/12/2016",
"items": [item]
]
And the just convert to json with NSJSONSerialization like this:
do {
let json = try NSJSONSerialization.dataWithJSONObject(mainDictionary, options: [])
} catch {
print(error)
}
UPDATE:
If you need to add values to array in dictionary you can do that like this:
if var items = mainDictionary["items"] as? NSMutableArray {
items.addObject(newItem)
mainDictionary["items"] = items
}
Related
I have the following JSON...
{
"id": "1000035148",
"petId": "3",
"ownerId": "1000",
"locationId": null,
"status": "Active",
“services”: [
{
"id": "5004",
“data”: 1,
“data1”: 0,
“data2": 63,
“data3": 0
}
]
}
And I'm only trying to return the following objects...
"id": "1000035148",
"petId": "3",
"ownerId": "1000",
"locationId": null,
"status": "Active"
How can I achieve this with the following code?
session.dataTask(with: request, completionHandler: { (data: Data?, response: URLResponse?, error: Error?) in
if let data = data {
do {
let jsonData = try JSONSerialization.jsonObject(with: data)
if let dictionary = jsonData as? [String: Any] {
if let nestedDictionary = dictionary["status"] as? [String: Any] {
for (key, value) in nestedDictionary {
print("Key: \(key), Value: \(value)")
}
}
}
print(jsonData)
} catch {
print("Error fetching data from API: \(error.localizedDescription)")
}
}
When I try to parse using the nestedDictionary = dictionary I get an error and it skips over the line. I'm confused on how to get just the key value pairs I want from the response.
Forget JSONSerialization and use Decodable with JSONDecoder:
struct DataModel: Decodable {
let id: String
let pedId: String?
let ownerId: String?
let locationId: String?
let status: String
}
do {
let dataModel = try JSONDecoder().decode(DataModel.self, from: data)
print("Status: \(dataModel.status)")
} catch ...
If you want to use JSONSerialization, note that status is not a dictionary, it's a String:
if let dictionary = jsonData as? [String: Any] {
if let status = dictionary["status"] as? String {
print("Status: \(status)")
}
}
My json looks like this:
[
{
"name": "sensei",
"owner": {
"login": "linkedin",
},
"description": "distributed realtime searchable database",
"fork": false,
},
{
"name": "linkedin-utils",
"owner": {
"login": "linkedin",
},
"description": "Base utilities shared by all linkedin open source projects",
"fork": false,
}
]
The structs I built are the following:
struct LinkedinData: Codable {
var name: String
var description: String
var owner: OwnerLogin
var fork: Bool
}
struct OwnerLogin: Codable {
var login: String
}
My code for parsing is this one:
import UIKit
class ViewController: UIViewController {
var linkedinData = [LinkedinData]()
override func viewDidLoad() {
super.viewDidLoad()
let urString : String = "https://api.github.com/orgs/linkedin/repos"
if let url = URL(string: urString) {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, response, error) in
if error != nil {
print(error!)
return //exit out of function
}
parseJSON(json: data!)
}
task.resume()
}
func parseJSON(json: Data) {
let decoder = JSONDecoder()
if let decodedData = try? decoder.decode(LinkedinData.self, from: json) {
linkedinData = [decodedData]
}
}
}
I tried for hours bút it seems impossible to parse the json and retreive the data I am looking for (name, description, owner.login and fork) in a collection type. Could you please help?
You should decode an array of LinkedinData, instead of just one, because your JSON has an array as its root:
[ <------- this "[" indicates an array
{
"name": "sensei",
"owner": {
"login": "linkedin",
},
Therefore, you should write:
if let decodedData = try? decoder.decode([LinkedinData].self, from: json) {
linkedinData = decodedData
}
if let decodedData = try? decoder.decode(LinkedinData.self, from: json) {
linkedinData = [decodedData]
}
replace this with
if let decodedData = try? decoder.decode([LinkedinData].self, from: json) {
linkedinData = decodedData
}
as your topmost object in JSON is an Array.
The JSON looks like this:
{
"00AK": {
"icao": "00AK",
"iata": "",
"name": "Lowell Field",
"city": "Anchor Point",
"country": "US",
"elevation": 450,
"lat": 59.94919968,
"lon": -151.695999146,
"tz": "America\/Anchorage"
},
"00AL": {
"icao": "00AL",
"iata": "",
"name": "Epps Airpark",
"city": "Harvest",
"country": "US",
"elevation": 820,
"lat": 34.8647994995,
"lon": -86.7703018188,
"tz": "America\/Chicago"
},
"00AZ": {
"icao": "00AZ",
"iata": "",
"name": "Cordes Airport",
"city": "Cordes",
"country": "US",
"elevation": 3810,
"lat": 34.3055992126,
"lon": -112.1650009155,
"tz": "America\/Phoenix"
}
}
As you can see the keys varies "00AK", "00AL", "00AZ", and so on. How do I parse this format of JSON?
let jsonData = //JSON DATA HERE
do {
let dict = try NSJSONSerialization.JSONObjectWithData(jsonData, options: []) as! NSDictionary
for (key, value) in dict {
let subDict = value as! NSDictionary
//Then you can access the values from subDict
} catch {
//ERROR HANDLING
}
So here it is I declare one structure as following
struct Model {
var iaco: String?
var iata: String?
var name: String?
var city: String?
var country: String?
var elevation: Int?
var lat: Double?
var lon: Double?
var tz: String? }
Then declare on array to hold the response result
var listOfModels = Array<Model>()
Then take a list of keys from response Dictionary and iterate over it to get result and store it in array
handleResponse { (response) in
for key in response.keys {
let dict = response[key] as? [String:Any]
var model = Model()
model.iaco = dict?["icao"] as? String
model.iata = dict?["iata"] as? String
model.name = dict?["name"] as? String
model.city = dict?["city"] as? String
model.country = dict?["country"] as? String
model.elevation = dict?["elevation"] as? Int
model.lat = dict?["lat"] as? Double
model.lon = dict?["lon"] as? Double
model.tz = dict?["tz"] as? String
listOfModels.append(model)
}
}
response.keys is used to get list of keys from dictionary.
You could try the below snippet:
func parseData() {
let jsonData = Data() /// your actual response data goes here...
do {
let dict = try JSONSerialization.jsonObject(with: jsonData, options: .allowFragments)
guard let swiftDict = dict as? [String : Any] else {
print("Not a valid response")
return
}
for (key, value) in swiftDict {
guard let valueDict = value as? [String: Any] else {
/// handle improper response here
return
}
/// Got the actual dictionary in 'valueDict'...
}
}
catch {
/// handle parsing error here
}
}
I have an issue with loading JSON results within swift (php connection).
I can retrieve JSON data but it will not let me assign it to a variable.
it always assigns the results as Optional.
The JSON Data:
{
"country": [{
"id": 1,
"name": "Australia",
"code": 61
}, {
"id": 2,
"name": "New Zealand",
"code": 64
}]
}
The xCode Output:
["country": <__NSArrayI 0x60000002da20>(
{
code = 61;
id = 1;
name = Australia;
},
{
code = 64;
id = 2;
name = "New Zealand";
}
)
]
Country Name: Optional(Australia)
Country Name: Optional(New Zealand)
The .swift file:
//function did_load
override func viewDidLoad() {
super.viewDidLoad()
//created RequestURL
let requestURL = URL(string: get_codes)
//creating NSMutable
let request = NSMutableURLRequest(url: requestURL!)
//setting the method to GET
request.httpMethod = "GET"
//create a task to get results
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil{
print("error is \(String(describing: error))")
return;
}
//lets parse the response
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String: Any]
print(json)
if let countries = json["country"] as? [[String: AnyObject]] {
for country in countries {
print("Country Name: \(String(describing: country["name"]))")
print("Country Code: \(String(describing: country["code"]))")
if let couname = country["name"] as? [AnyObject] {
print(couname)
}
if let coucode = country["code"] as? [AnyObject] {
print(coucode)
}
}
}
} catch {
print("Error Serializing JSON: \(error)")
}
}
//executing the task
task.resume()
}
You need to unwrap the optional before you try to use it via string interpolation. The safest way to do that is via optional binding:
Please use below code, which will work for you.
if let countries = json["country"] as? [[String: AnyObject]] {
for country in countries {
print("Country Name: \(country["name"] as! String)")
print("Country Code: \(country["code"] as! String)")
if let couname = country["name"] as? String {
print(couname)
}
if let coucode = country["code"] as? Int {
print(coucode)
}
}
}
I'm trying to create an array of dictionaries from JSON response.
Here is the code.
_ = postView.textView.rx.text
.subscribe(onNext: {[unowned self] _ in
let client = Alamofire.SessionManager.default
_ = client.request(Router.getFriends())
.rx_responseJSON()
.subscribe(onNext: { [weak self] data in
var names = [String]()
do {
let json = try JSONSerialization.jsonObject(with: data) as? [String: Any], //'var' declarations with multiple variables cannot have explicit getters/setters
let friends = json["user"] as? [[String: Any]] {
for friend in friends {
if let name = friend["first_name"] as? String {
names.append(name)
}
}
}
} catch {
print("Error deserializing JSON: \(error)")
}
print(names)
}, onError: { (error) -> Void in
debugPrint("Error: \(error)")
})
})
This is the error I'm getting
'var' declarations with multiple variables cannot have explicit
getters/setters
This is the JSON response,
{
"user": [
{
"id": 2,
"first_name": "Knysys",
"photo": "https://graph.facebook.com/437334666655912/picture/?type=large",
"last_seen_event": null,
"blocked": false
},
{
"id": 3,
"first_name": "ATester",
"photo": "https://graph.facebook.com/379988632393252/picture/?type=large",
"last_seen_event": 7,
"blocked": false
}
]
}
The desired output is this,,
var friends = [
[
"firstName": "SmartApps",
"photo": "https://graph.facebook.com/1248984075179327/picture/?type=large"
],
[
"firstName": "Knysys",
"photo": "https://graph.facebook.com/437334666655912/picture/?type=large"
],
[
"firstName": "ATester",
"photo": "https://graph.facebook.com/379988632393252/picture/?type=large"
]
]
Thanks in advance!
You forgot the if in the line let json = ...
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
let friends = json["user"] as? [[String: Any]] {
for friend in friends {
if let name = friend["first_name"] as? String {
names.append(name)
}
}
}
} catch {
print("Error deserializing JSON: \(error)")
}
Here is the code that worked,
let client = Alamofire.SessionManager.default
_ = client.request(Router.getFriends())
.rx_responseJSON()
.subscribe(onNext: { [weak self] data in
self?.friends.removeAll()
let json = data as? [String: Any]
let friends = json?["user"] as! [[String: Any]]
for i in 0 ..< friends.count{
let firstName: String = (friends[i]["first_name"] as! NSString) as String
let photo: String = (friends[i]["photo"] as! NSString) as String
let dict = [
"firstName" : firstName,
"photo" : photo
]
self?.friends.append(dict)
}
self?.friendTableView.reloadData()
self?.friendTableView.sizeToFit()
}, onError: { (error) -> Void in
debugPrint("Error retrieving friends: \(error)")
})