Accessing JSON data with Swift - json

I have an array of JSON data from the following call:
guard let json = (try? JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [Any] else {
print("Not containing JSON")
return
}
when I run print(json) I get the following in the output:
[{
"CREATED_BY" = "DOMAIN\\USER";
"CREATED_DATE" = "2016-11-28T08:43:59";
STATUS = U;
"WIDGET_NUMBER" = K11;
"UPDATED_BY" = "<null>";
"UPDATED_DATE" = "<null>";
}, {
"CREATED_BY" = "DOMAIN\\USER";
"CREATED_DATE" = "2016-05-09T08:46:23";
STATUS = U;
"WIDGET_NUMBER" = 89704;
"UPDATED_BY" = "<null>";
"UPDATED_DATE" = "<null>";
}]
I am trying to get all of the WIDGETNUMBER values in the array of JSON data. The json variable is a Any type and I have not been able to convert to a struct so far. Is there an easy way to get the elements from the JSON objects?

It looks like you have an array of dictionaries
for item in json {
if let item = item as? [String: Any], let widgetNo = item["WIDGET_NUMBER"] {
print(widgetNo)
}
}

Your content is array of Dictionary, so that you must convert each element Dictionary to Json
for dic in content {
do {
let jsonData = try JSONSerialization.data(withJSONObject: dic, options: .prettyPrinted)
print(jsonData)
} catch {
print(error.localizedDescription)
}
}
Or you can read value of WIDGET_NUMBER direct from Dictionary
for dic in content {
print(dic["WIDGET_NUMBER"] ?? "Not found")
}

Joakim's answer is spot on for getting the widget number. For your struct, be sure to add something like this as an initializer to map your object.
let widgetNumber: Int
let user: String
init?(json:[String:Any]) {
guard let widgetNumber = json["WIDGET_NUMBER"] as? Int,
let user = json["CREATED_BY"] as? String else { return nil }
self.widgetNumber = widgetNumber
self.user = user
}

If you just want an array of widget numbers you could use the reduce function which iterates the dictionaries in the array and extracts the widget numbers:
Using your data I put this in a storyboard:
let json = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves) as! [[String: Any]]
let widgetNumbers = json?.reduce(into: [String]()){ (accum, dict) in
guard let widget = dict["WIDGET_NUMBER"] as? String else { return }
accum.append(widget)
}
widgetNumbers // -> ["K11", "89704"]

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)
}
}
}

Accessing Object Attributes from JSON, Swift3

let url = URL(string: "http://192.168.30.243:5000/trippy/destination/info?id=4864cc0a-8")
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error != nil {
print ("ERROR")
}
else {
if let content = data {
do {
//Array
let myJson = try JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject
print(myJson)
if let information = myJson as? NSDictionary {
print (information.value(forKey: "EmergencyNumbers")!)
if let number = information.value(forKey: "EmergencyNumbers") as? NSArray {
//This is the part I am unsure about
if let description = number[0] as? AnyObject {
//I know do not know how to access the object's attribute values
}
}
}
}
catch {
}
}
}
}
task.resume()
}
I have used JSON to parse data from the web. I have utilized a dictionary to access the information and then an array to get the data from the certain key. Within this array are lie some objects. How do I access each of these objects' properties' values?
JSON Example:
{
Currency = testCurrency;
DestinationId = "4864cc0a-8";
DialCode = testDialCode;
DoesntUseMetricSystem = 0;
DrinkingAge = 16;
DriverLicense = 1;
EmergencyNumbers = (
{
Description = "Emergency Pizza Delivery";
Id = 1;
Number = 6969;
}
);
Id = 1;
IsNorthHemisphere = 1;
OfficialLanguage = {
Id = 1;
Name = testLanguage;
};
PowerGridVoltage = 226;
PowerSocket = dk;
Telecoms = nonern;
Tipping = 2;
WidelySpokenLanguages = (
{
Id = 2;
Name = testtLanguage;
}
);
WrongSideOfRoad = 0;
}
I see you are coming from Objective-C world, so first I'd recommend you give up using NSArray, NSDictionary etc. in favor of their Swift counterparts Array and Dictionary:
let task = URLSession.shared.dataTask(with: url!) { data, response, error in
...
let JSON = try? JSONSerialization.jsonObject(with: data!, options: [])
if let dictionary = JSON as? [String: Any],
let emergencyNumbers = dictionary["EmergencyNumbers"] as? [[String: Any]]
{
emergencyNumbers.forEach { numbers in
print(numbers["Description"] as? String)
print(numbers["Id"] as? Int)
print(numbers["Number"] as? Int)
}
}
}
By the way [String: Any] is just a syntactic sugar for Dictionary<String, Any>. Same applies to arrays as well: [[String: Any]] is for Array<Dictionary<String, Any>>.
As always, don't use NSArray / NSDictionary in Swift. You throw away the type information.
The root object is a dictionary ([String:Any]), the value for key EmergencyNumbers is an array ([[String:Any]]). Use a loop to iterate thru the array.
if let root = try JSONSerialization.jsonObject(with: content) as? [String:Any] {
print(myJson)
if let emergencyNumbers = root["EmergencyNumbers"] as? [[String:Any]] {
for emergencyNumber in emergencyNumbers {
let description = emergencyNumber["Description"] as? String
let id = emergencyNumber["Id"] as? Int
let number = emergencyNumber["Number"] as? Int
print("description", description ?? "n/a")
print("id", id ?? "n/a")
print("number", number ?? "n/a")
}
}
Some other bad habits:
.mutableContainers is completely meaningless in Swift. The hilarious thing is, everybody who passes the option .mutableContainers assigns the result to an immutable constant.
The unspecified JSON type in Swift 3+ is Any not AnyObject
valueForKey, a KVC method, is inappropriate for this purpose, use objectForKey or key subscription. With Swift native types don't use it at all.

Swift and accessing nested JSON collections

I am accessing a CMS with a pre-baked JSON output and it uses the following data structure. I am struggling to get down into the nested collections to get the version or loop through the categories.
{
results: [
{
pageData: {
info: {
version: "1"
},
categories: [
{
name: "Cat 1"
},
{
name: "Cat 2"
}
]
}
}
]
}
Here is the code I was attempting to use. Any help is appreciated!
guard let json = json, let results = json["results"], let pageData = results["pageData"], let info = pageData["info"] as? [String:Int], let version = info["version"],
let categories = Category.getCategories(json: json) else {
self.completionParse(RequestResult.errorParsing, self.categoriesResult)
return
}
To access the info and categories dictionaries you need to first access results Array and pageData that is inside the first object of results array.
guard let json = json, let results = json["results"] as? [[String:Any]],
let firstDic = results.first, let pageData = firstDic["pageData"] as? [String:Any],
let info = pageData["info"] as? [String:Int], let version = info["version"],
let categories = Category.getCategories(json: pageData) else {
self.completionParse(RequestResult.errorParsing, self.categoriesResult)
return
}
Tested below code on playground. This code is in latest swift 3.
if let dictResponse = json as? [String:Any] {
// This will get entire dictionary from your JSON.
if let results = dictResponse["results"] as? [[String:Any]]{
if let pageData = results.first? ["pageData"] as? [String:Any]{
if let info = pageData["info"] as? [String:Any]{
if let version = info["version"] as? String{
print(version)
// This will print 1
}
}
if let categories = pageData["categories"] as? [[String:Any]]{
// This will give you a category array. Later on you can iterate and get the dictionary’s value of each element.
for categoriesObj in categories.enumerated(){
if let name = categoriesObj.element["name"]{
print(name)
}
}
}
}
}
}

Get data from json array swift 2

I'm trying to get data drom the json array, this is the code that i'm trying, the thing is that i would like to get only the name that is inside this json
{
"tag": "getuser",
"success": 1,
"error": 0,
"uid": "56108b7e651ad2.95653404",
"user": {
"name": "2",
"phone": "2",
"email": "2"
}
}
I tryied this
let jsonData:NSDictionary = try NSJSONSerialization.JSONObjectWithData(urlData!, options:NSJSONReadingOptions.MutableContainers ) as! NSDictionary
let name = jsonData["user"]
print("Nombre del usuarioes: \(name)")
But this prints the whole user data, name, phone and email, how can i be able to print only the name or only the email?
You don't have to use a library and you don't have to use key-value coding.
The same way you're already using subscripting for your dictionary with this:
let name = jsonData["user"]
you just have to continue subscripting to find your value.
Example:
do {
let jsonData = try NSJSONSerialization.JSONObjectWithData(urlData!, options: []) as! NSDictionary
let user = jsonData["user"]!
let name = user["name"]
print(name)
} catch {
print(error)
}
Even better with safe unwrapping:
do {
if let data = urlData, let jsonData = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? NSDictionary {
if let user = jsonData["user"] as? NSDictionary, let name = user["name"] as? String {
print(name)
}
}
} catch {
print(error)
}
Note: in JSON, a dictionary is defined by {} and an array is defined by []. What you have here is a dictionary containing a dictionary, not an array (cf your question title).
A great library to decode json is SwiftyJSON
you can get sub-scripted data from the json like so
import SwiftyJSON
if let dataFromString = jsonString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) {
let json = JSON(data: dataFromString)
let name = json["user"]["name"].string
print(name)
}
Use your code, then get the field from jsonData by this:
let name = jsonData.valueForKeyPath("user.name") as! String
let email = jsonData.valueForKeyPath("user.email") as! String

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