Getting mySql data from url in swift 3 - again - swift

I have asked this seemingly very simple and straight forward question a few times now, never got a solution.
I have a url to obtain mySql data
// 1. get url
let url = URL(string:"http://www.mobwebplanet.com/phpWebService/sample.php")
// 2. Fetch data from url
let data = try? Data(contentsOf: url!)
//playground Output is: 102 bytes. So obviously xcode gets the response data from the URL.
Then I move on to extracting the data:
//3. Create a dictionary from data:
let urlDict = try? JSONSerialization.jsonObject(with: data!, options: [])
// playground Output is: [["Latitude": "37.331741", "Address": "1 Infinite Loop Cupertino, CA", "Name": "Apple", "Longitude": "-122"]]
print(urlDict!)
// playground Output is: "(\n {\n Address = "1 Infinite Loop Cupertino, CA";\n Latitude = "37.331741";\n Longitude = "-122";\n Name = Apple;\n }\n)\n"
My understanding is urlDict is of a Any type. Am I correct?
My biggest question is how can I (cast or convet) urlDict so that I can access the value using key=>value? Like this:
urlDict!["Address"] Outputs "1 Infinite Loop Cupertino, CA"
urlDict!["Latitude"] Outputs "37.331741"...
I am a newbie to Swift so I am doing this as an exercise, any help will be greatly appreciated.

Your JSON response returns an Array of Dictionary objects. So you just need to cast correctly.
let urlString = "http://www.mobwebplanet.com/phpWebService/sample.php"
let url = URL(string: urlString)!
let data = try? Data(contentsOf: url)
if let json = try? JSONSerialization.jsonObject(with: data!, options: []) as? [[String:Any]] {
for location in json! {
print(location["Longitude"])
print(location["Latitude"])
print(location["Address"])
}
}
Output:
Optional(-122)
Optional(37.331741)
Optional(1 Infinite Loop Cupertino, CA)

Related

How to handle dynamic keys with single element as value in Swift

I'm having a problem figuring out how to handle dynamic keys with a single value one level deep. I've seen a few examples but they appear to handle other cases.
Here's an example.
[
{ "asdofjiodi": "asdofidj.com" },
{ "sadjlkj": "iejjol.com" },
{ "ijijwjljlijl": "adsijf.com" },
{ "jgncmkz": "mlkjaoijf.com" }
]
Any ideas on how I accomplish this with Codable or CodingKey? This is what I'd like for the end result.
["asdofidj.com", "iejjol.com", "adsijf.com", "mlkjaoijf.com"]
let url = Bundle.main.url(forResource: "file", withExtension: "json")!
let data = try! Data(contentsOf: url)
let decoder = JSONDecoder()
// NOTE: The below line doesn't work because I'm not sure how to do the encoding/decoding
try? decoder.decode([[String: String]].self, from: data)
First of all, is not a valid JSON. A "Valid JSON" can be a JSON Array (multiple json objects) or a single JSON object (starts and ends with { and })
After cleaning this...
You are trying to make a dictionary (json object) from a data. You don't need JSONDecoder to accomplish this. Try using JSONSerialization with jsonObject static function...
let data = Data("{\"asdofjiodi\": \"asdofidj.com\",\"sadjlkj\": \"iejjol.com\",\"ijijwjljlijl\": \"adsijf.com\",\"jgncmkz\": \"mlkjaoijf.com\"}".utf8)
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
let values = json?.map({ $1 })
print(values)
I Hope I helped!
JSONSerialization Apple documentation
Here is a minimal working example, given the JSON in your question:
let json = """
[
{ "asdofjiodi": "asdofidj.com" },
{ "sadjlkj": "iejjol.com" },
{ "ijijwjljlijl": "adsijf.com" },
{ "jgncmkz": "mlkjaoijf.com" }
]
"""
let data = Data(json.utf8)
let decoder = JSONDecoder()
do {
let decodedJson = try decoder.decode([[String: String]].self, from: data)
let values = decodedJson.compactMap(\.values.first)
print(values)
} catch {
print("Error: \(error.localizedDescription)")
}
If this doesn't appear to work for you, it may be related to how you load in the JSON.

Swift Encoding a JSON dictionary [String: Any], can't get rid of the quotes

We are grabbing some data from an API, which we decode into a [String: Any] dictionary.
We want to then take this dictionary, and mutate a value for a key "$twitter_card".
Then we want to encode that back into Data, which we send back to the API.
print(seeEditResponseString)
guard let data = seeEditResponseString.data(using: .utf8) else {return}
if let dict = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], var dataDict = dict["data"] as? [String: Any] {
let summary: Any = "summary"
print(dataDict)
dataDict["$twitter_card"] = summary
print(dataDict)
let url = URL(string: "https://api2.branch.io/v1/url?url=\(link)")!
var request = URLRequest(url: url)
request.httpMethod = "PUT"
let jsonData = try? JSONSerialization.data(withJSONObject: ["branch_key": EnvConstants.branchKey, "branch_secret": EnvConstants.branchSecretKey, "data": dataDict])
request.httpBody = jsonData
Print statement before setting "$twitter_card":
["~feature": TwitterShare, "$publicly_indexable": 1, "$one_time_use": 0, "~id": 881331908143151724, "~creation_source": 3, "~channel": twitter, "$og_description": HELLO WORLD, "$twitter_app_country": US, "$twitter_card": summary_large_image]
After setting "$twitter_card":
["~feature": TwitterShare, "$publicly_indexable": 1, "$one_time_use": 0, "~id": 881331908143151724, "~creation_source": 3, "~channel": twitter, "$og_description": HELLO WORLD, "$twitter_app_country": US, "$twitter_card": "summary"]
Notice how before there aren't quotes in the value, but after there is. We believe the API request is failing because of this, but can't figure out how to match the same data type on the request back.
EDIT: here is the response as a String:
"{\"data\":{\"$og_title\":\"Locker Room\",\"$publicly_indexable\":true,\"$deeplink_path\":\"open?link_click_id=881284646317326515\",\"~creation_source\":3,\"$locally_indexable\":true,\"$og_description\":\"HELLO WORLD\",\"$uri_redirect_mode\":\"2\",\"$identity_id\":\"880941693229513892\",\"$twitter_card\":\"summary_large_image\",\"$og_image_url\":\"https://bettylabs.io/lockerroom_logo_play_wide.png\",\"room\":\"91939938-1171-4e61-9ecf-5934b92298cf\",\"~feature\":\"TwitterShare\",\"url\":\"https://dummylit.com/CScjyeLyidb\",\"$twitter_title\":\"Disco Dev\",\"$fallback_url\":\"https://dummylit.com/room/91939938-1171-4e61-9ecf-5934b92298cf\",\"+url\":\"https://dummylit.com/CScjyeLyidb\",\"$ios_deeplink_path\":\"open?link_click_id=881284646317326515\",\"$canonical_identifier\":\"room/91939938-1171-4e61-9ecf-5934b92298cf\",\"$twitter_app_country\":\"US\",\"inviterId\":\"a5e7f4b2-580a-4661-aad3-2c78bb4a78c7\",\"$one_time_use\":false,\"~id\":\"881743970732394436\",\"~channel\":\"twitter\",\"$twitter_description\":\"Green Sock\"},\"type\":0,\"feature\":\"TwitterShare\",\"channel\":\"twitter\"}"

HTTP Response String to 2D Swift Array

I am wandering if anyone has done anything similar to this. I make a http request and the response is a two dimensional array, for example,
[["Column1","Column2","Column3","Column4"],["1","2","3","4"]]
I am trying to convert the "text/array" in the http response to a 2D array in Swift. Has anyone done anything like this?
I understand that I can have the http response come back in the JSON format and the use of JSONDecode, but that is not what I want to do in this particular case.
try this:
let responseString = "[[\"Column1\",\"Column2\",\"Column3\",\"Column4\"],[\"1\",\"2\",\"3\",\"4\"]]"
let data = responseString.data(using: .utf8)!
if let output : [[String]] = try! JSONSerialization.jsonObject(with: data, options: []) as? [[String]]{
print(output)
}
output:
[["Column1", "Column2", "Column3", "Column4"], ["1", "2", "3", "4"]]

Send Core Data object to post api Alamofire multipartFormData

I have a screen on my app that I get some fields and save on my object Order. This object is my Core Data Object. After saving it, I need to send it to my backend through Alamofire POST multipartFormData.
The problem is that this is a Core Data Object (not Codable) and I need to send Data type on multipartFormData. How can I convert my object to Data? Is there another way of doing it?
What I've done:
let order = Order(context: DatabaseController.getContext())
order.orderItem = orderItem
order.product = product
order.value = value
order.date = date
Alamofire part:
Alamofire.upload (
multipartFormData: { multipartFormData in
multipartFormData.append(order, withName: "order")
},
to: url,
headers: headers,
encodingCompletion: { encodingResult in
The problem is how to put my object Order inside multipartFormData?
Could anyone help me please?
Updated:
Ok, sending the whole object didn't work, my api didn't accept, so I made a specific json only with the fields needed and turned it a Data type:
(PS: files are Data type from images user choose, even from camera or gallery)
var files = Dictionary<Data, String>()
var jsonFiles = [[String: String]]()
var jsonOrder = [String: Any]()
for file in files {
let dict : [String: String] = [ "orderImageIdLocal": uuidOrderImageIdLocal,
"orderItemAnalysisIdLocal": uuidAnalysisIdLocal,
"urlImageLocal": "\(imageId).jpg"]
jsonFiles.append(dict)
}
jsonOrder = [ "reason": "\(textViewReason)",
"orderImagess": jsonFiles,
"orderAnalysisId": "",
"orderIdLocal": "\(uuidAnaliseIdLocal)",
"orderId": "\(orderId ?? "")",
"typeSolicitation": "\(typeSolicitation)"]
Then I convert it to Data type like you said and send to Alamofire like above:
let orderData = try? JSONSerialization.data(withJSONObject: jsonOrder, options: .prettyPrinted) {
My problem now is that my api expect a zip file with those images user took from camera or gallery. So I am trying to use ZIPFoundation. I still don't know how to zip it and send. Should I zip each picture as Data type? Then transform zip file into Data type so I can send through multipartFormData.append?
I have tried: here and here
Here the code as an extension of NSManagedObject which creates dictionary from the attributes name.
extension NSManagedObject {
func toData() -> Data? {
let keys = Array(self.entity.attributesByName.keys)
let dict = self.dictionaryWithValues(forKeys: keys)
do {
let jsonData = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
return jsonData
}
catch{}
return nil
}
}
Usage:
let jsonData = order.toData()
multipartFormData.append(jsonData, withName: "order")

Swift: How to convert string to dictionary

I have a dictionary which i convert to a string to store it in a database.
var Dictionary =
[
"Example 1" : "1",
"Example 2" : "2",
"Example 3" : "3"
]
And i use the
Dictionary.description
to get the string.
I can store this in a database perfectly but when i read it back, obviously its a string.
"[Example 2: 2, Example 3: 3, Example 1: 1]"
I want to convert it back to i can assess it like
Dictionary["Example 2"]
How do i go about doing that?
Thanks
What the description text is isn't guaranteed to be stable across SDK versions so I wouldn't rely on it.
Your best bet is to use JSON as the intermediate format with NSJSONSerialization. Convert from dictionary to JSON string and back.
I created a static function in a string helper class which you can then call.
static func convertStringToDictionary(json: String) -> [String: AnyObject]? {
if let data = json.dataUsingEncoding(NSUTF8StringEncoding) {
var error: NSError?
let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: &error) as? [String: AnyObject]
if let error = error {
println(error)
}
return json
}
return nil
}
Then you can call it like this
if let dict = StringHelper.convertStringToDictionary(string) {
//do something with dict
}
this is exactly what I am doing right now. Considering #gregheo saying "description.text is not guaranteed to be stable across SKD version" description.text could change in format-writing so its not very wise to rely on.
I believe this is the standard of doing it
let data = your dictionary
let thisJSON = try NSJSONSerialization.dataWithJSONObject(data, options: .PrettyPrinted)
let datastring:String = String(data: thisJSON, encoding: NSUTF8StringEncoding)!
you can save the datastring to coredata.