Parsing a nested JSON as a dictionary with Swift / SwiftyJSON - ios

I'm using SwiftyJSON to parse a nested JSON. The JSON is used to populate a form where the user is shown the "keys" from the JSON to select from and then the corresponding values to the selection are used to calculate a score.
I've tried to parse the JSON and the parsing works well to get the rest of the data (e.g. the question) but when I try to parse the portion of the JSON where the scores (key: values) are, I get null.
{
"Question": "Pick a Number from the given values",
"Answer_Choices": {
"10": "6",
"9": "6",
"8": "3",
"7": "3",
"6": "1"
}
}
In the above code I want to display the left numbers to the user where they pick the 'keys' and correspondingly I will assign the values the values to contribute to the user's score, e.g. if the user selects 8, I'll assign them 3. I'm not sure how I can cast the key as well as values dynamically. They always fill up as null.
Question is parsed as:
var question = JSON["Question"].string
var answerChoices = JSON["Answer_Choices"].dictionaryObject // I know this is probably not correct.

You are pretty close. Here is how you can parse to get separate arrays for answers and points
guard let dict = json["Answer_Choices"].dictionaryObject as? [String:String] else {
return
}
let answerArray = Array(dict.keys)
let pointsArray = Array(dict.values)

Related

How to correctly send array with objects in JSON Swift iOS

Hello I am beginner and trying to understand how to send an array with objects. Does the server understand what an array is like Int, Strings or Booleans? Do you have to send the array in a string for JSON? What I do not understand?
var productsResult = ""
let encoder = JSONEncoder()
let productObject = ProductUsed(name: "Custom name", reason: "This Reason", apply_way: "Intravenous infusion", dosing: "2x", date_start: "22-02-1999", date_end: "22-03-2003")
do {
let result = try encoder.encode([productObject])
if let resultString = String(data: result, encoding: .utf8) {
print(resultString)
productsResult = resultString
}
} catch {
print(error)
}
json["products_used"] = productsResult
And I sent to server with parameters like this:
parameters: ["pregnancy_week": 0, "body_height": 198, "initials": "John Appleseed", "heavy_effect": false, "sex": "Male", "pregnancy": false, "month_of_birth": 3, "reaction": "No option checked", "additional_info": "Eeee", "products_used": "[{\"date_end\":\"22-03-2003\",\"dosing\":\"2x\",\"date_start\":\"22-02-1999\",\"apply_way\":\"Intravenous infusion\",\"name\":\"Custom name\",\"reason\":\"This Reason\"}]", "description": "Eeee", "result": "Recovery without lasting consequences", "year_of_birth": 1983, "day_of_birth": 11, "issue_date": "15-11-2020", "body_weight": 78]
but printed "resultString" in log and looks good...
[{"date_end":"22-03-2003","dosing":"2x","date_start":"22-02-1999","apply_way":"Intravenous infusion","name":"Custom name","reason":"This Reason"}]
What's wrong in my code and why I have " \ " between words in "products_used" key?
JSON, unlike XML, does not specify the structure and type explicitly. This means that the server must know what JSON data to expect.
In JSON there are a few value types (https://www.w3schools.com/js/js_json_syntax.asp):
a string
a number
an array
a boolean
null
a JSON object (a dictionary with tags like { "first" : "John", "last" : "Doe" }). This allows nesting.
A JSON object is a set of tag-value pairs. The tag and value are separated by : and pairs are separated by ,.
An array is a list of JSON values. So for example [ "hello", world" ] is a JSON array with 2 strings and [ 12, 54 ] is a JSON array with two numbers.
Your parameter list ["pregnancy_week": 0, "body_height": 198, ... is not an array but a dictionary instead. A Swift dictionary is translated to an JSON object, not a JSON array.
The \ you see printed acts as escape character. This escape character is used to allow you to have a " inside the string.
That's just a few things that I hope will help understand things a bit better. Your questions are pretty basic, which is fine and it's great you want to understand things. But instead of us explaining everything here, I think it would be best if you'd read about the structure of JSON and how JSON works in Swift on your own.

Dictionary [String: String] keys order changed when converted to array swift

I have a dictionary like below,
var dataSource: [String: String] = ["FirstName": "Austin",
"ListName": "Michael",
"Address": "Street Address",
"City": "Chennai"]
I want to populate these values in a UITableView, so I tried to get all the keys from Dictionary to an Array like below,
let dataArray = Array(dataSource.keys)
I got the output as [String] like,
["LastName", "FirstName", "City", "Address"]
The problem is, the order of the keys has changed, I want the array in the same order as dictionary has.
Can you anyone help?
Use plain dictionary as tableview datasource is bad idea.
However Dictionary can not be sorted. So it doesn't matter in what order you add your keys-values to the dictionary.
If you need sorted then use array of dictionary instead.
You should use models instead of plain dictionary that is easy to maintain :]
like
struct User {
var firstName:String?
var lastName:String?
var address:String?
var city:String?
}

Parsing an array in swift with null values (not nil)

I'm calling webservice in swift for an iOS app, i have the webservice returns data in the form of array .. like this :
["354", "Air Conditioning", "null", "2", "Street EG", null, null, null, null, null, "50", "20", "2017-01-22T14:30:46Z", "27", "24", "18", "13", "0", null, null, null, null ] ..
the problem is that when it populates an array it suppresses the null values and reduces the length of the array which is not right, i need the data to be "null" if it is null or nil because i get values by index and each index is know to be null or with value but it must be there
Use optionals. Your array would be
var array = [String?]
With optionals, you can accept nil values.
When you append the value to the array, now it can accept nil
If you convert this JSON with something like JSONSerialization.jsonObject(with: data), the resulting array doesn't suppress the null entries. They're represented by NSNull objects. If your null entries are suppressed, then you should edit your question to share the code that is doing that. Standard JSON parsing routines will preserve these values without incident. For example, in Swift:
guard let jsonObject = try? JSONSerialization.jsonObject(with: data), let array = jsonObject as? [Any] else {
print("can't parse it")
return
}
for object in array {
if object is NSNull {
print("Hey, it's null!")
} else {
print("It's not null, it's \(object)")
}
}
You can see that the null values are preserved, represented with NSNull (except the first one, which because it's in quotes, is a string with four characters, "null").

Update multiple labels with values from a dictionary?

I'm trying to make an app that will select an index at random, something like 0-1000 and then print the key, value, and link of the selected number to three seperate labels on the iPhone simulator.
So from my example, I want to randomly select "0" or "1" and if for instance "1" was chosen; then the key, value, and link information would each be printed to three separate labels on the simulator. The following is what I've been working on in playgrounds. Is there a better way to go about this?
var spDictionary: [String: [String:String]] = [
"0": ["key": "AMZN", "value": "AMAZON", "link": "yahoo"],
"1": ["key": "AAPL", "value": "APPLE", "link": "yahoo2"],
]
And for the random aspect I think it would be something like this but I'm not sure? Sorry for the newbie question.
let randomIndex: Int = Int(arc4random_uniform(UInt32(spDictionary.count)))`
Even for small data structures it's worth it to create a custom class or struct
struct Data {
let key : String
let value : String
let link : String
}
Create an object
let data = Data(key: "AMZN", value: "AMAZON", link: "yahoo")
Get a property
let link = data.link
and you can declare your dictionary
var spDictionary : [String: Data] = ...

How to push data with multiple types in Firebase?

I want to push an array that has strings, numbers and date. Do I have to update individually or is there another way I can accomplish this?
Example:
var categories : [String] = self.parseCategories()
var standbyDataStrings = [
"firstName":firstName,
"lastName":lastName,
"categories": categories,
"time_stamp":self.date.timeIntervalSince1970
]
var standbyDataNums = [
"radius":nf.numberFromString(self.helpRadiusLabel.text!),
"duration":nf.numberFromString(self.helpDurationLabel.text!)
]
standbyUserRef.updateChildValues(standbyDataStrings)
standbyUserRef.updateChildValues(standbyDataNums) // this gives me a error "string is not identical to NSObject"
Combining standByDataStrings and standbyDataNums gives me an error.
Or is there a way to retrieve a string from Firebase and using it as an int. It gets stored as a String with the quotations.
The Firebase API expects an NSDictionary for updateChildValues. A NSDictionary can't contain nil values. A normal Swift dictionary on the other hand can contain nil values.
The return type of numberFromString is NSNumber?, so Swift infers that the dictionary might contain nil and so it can't be passed to updateChildValues. By explicitly forcing non-nil values with ! you can make this code compile:
var standbyDataNums = [
"radius":nf.numberFromString(self.helpRadiusLabel.text!)!,
"duration":nf.numberFromString(self.helpDurationLabel.text!)!
]
standbyUserRef.updateChildValues(standbyDataNums) // now type checks

Resources