Encode url string to Dictionary In my case: Some value have = inside - ios

I'm trying to convert decode to dictionary from the below url encoded string. The normal method of doing so is given below. In my case it is not working. Also i need to remove any character like \u{05}
let params = str.components(separatedBy: "&").map({
$0.components(separatedBy: "=")
}).reduce(into: [String:String]()) { dict, pair in
if pair.count == 2 {
dict[pair[0]] = pair[1]
}
}
My url encoded string is
"id=sfghsgh=sbfsfhj&name=awsjdk_fs\u{05}"
I'm expecting result as
{
"id" = "sfghsgh=sbfsfhj",
"name" = "awsjdk_fs"
}
How it is possible to achive?

Piggyback on URLComponents:
var components = URLComponents()
components.query = "id=sfghsgh=sbfsfhj&name=awsjdk_fs"
components.queryItems
// => Optional([id=sfghsgh=sbfsfhj, name=awsjdk_fs])
let list = components.queryItems?.map { ($0.name, $0.value) } ?? []
// [("id", Optional("sfghsgh=sbfsfhj")), ("name", Optional("awsjdk_fs"))]
let dict = Dictionary(list, uniquingKeysWith: { a, b in b })
// ["name": Optional("awsjdk_fs"), "id": Optional("sfghsgh=sbfsfhj")]
If you need a [String: String] rather than [String: String?]:
let list = components.queryItems?.compactMap { ($0.name, $0.value) as? (String, String) } ?? []
// [("id", "sfghsgh=sbfsfhj"), ("name", "awsjdk_fs")]
let dict = Dictionary(list, uniquingKeysWith: { a, b in b })
// ["name": "awsjdk_fs", "id": "sfghsgh=sbfsfhj"]

Related

Flatten an array of dictionaries to one dictionary

I am having an array of dictionaries with columnId and columnValue as a pair. Now i need to flatten it as columnId as the key and columnValue as the value of it. How is it possible to do with swift higher order functions?
let arrayOfDictionaries = [["columnId": 123, "columnValue": "sample text"], ["columnId": 124, "columnValue": 9977332]]
//The end result should be:
flattenedDictionary: [String: Any] = ["123": "sample text", "124": 9977332]
Note: Result dictionary will be in the form of [String: Any]
This would work:
func flatten(_ pairs: [[String: Any]]) -> [String: Any] {
pairs.reduce(into: [String: Any]()) {
if let id = $1["columnId"] as? Int, let value = $1["columnValue"] {
$0["\(id)"] = value
}
}
}
You can do this in two steps;
Convert your input array into a sequence of key-value pairs using compactMap
Convert the sequence back into a dictionary using Dictionary(uniqueKeysWithValues:)
let arrayOfDictionaries = [["columnId": 123, "columnValue": "sample text"], ["columnId": 124, "columnValue": 9977332]]
let tupleArray:[(String,Any)] = arrayOfDictionaries.compactMap { dict in
guard let id = dict["columnId"], let value = dict["columnValue"] else {
return nil
}
return ("\(id)",value)
}
let flattenedDictionary: [String: Any] = Dictionary(uniqueKeysWithValues: tupleArray)
Note that this code will throw an exception if there are duplicate keys. You should either take steps to ensure the columnId values are unique or use Dictionary(keysAndValues:, uniquingKeysWith:) to resolve id clashes.

Create Dictionary from Array in Swift 5

I need to create a dictionary from array with custom type for first index of the array.
Sample array : ["ABC","ZYZ","123"]
Required result : [{"name" : "ABC", "type:"A"},{"name" : "ZYZ", "type:"B"},{"name" : "123", "type:"B"}]
Note type A for first index.
My code
for url in urlArray {
urlDict["name"] = url
}
You can do a map, and then individually change the type of the first dictionary:
var dicts = urlArray.map { ["name": $0, "type": "B"] }
dicts[0]["type"] = "A"
Seeing how all your dictionary keys are all the same, and that you are sending this to a server, a Codable struct might be a better choice.
struct NameThisProperly : Codable {
var name: String
var type: String
}
var result = urlArray.map { NameThisProperly(name: $0, type: "B") }
result[0].type = "A"
do {
let data = try JSONDecoder().encode(result)
// you can now send this data to server
} catch let error {
...
}
I suppose you can use a high order function such as map or reduce
Here is an example using reduce
var array = ["ABC","ZYZ","123"]
var result = array.reduce([[String: String]](), { (previous, current) -> [[String: String]] in
let type = previous.count == 0 ? "A" : "B"
let dictForCurrent = [
"name": current,
"type": type
]
return previous + [dictForCurrent]
})
print(result)
The result:
[["type": "A", "name": "ABC"], ["type": "B", "name": "ZYZ"], ["name":
"123", "type": "B"]]
Use reduce to convert array to dictionary:
let resultDict: [String: String]
= array.reduce(into: [:]) { dict, url in
dict["name"] = url
}
The result will look like:
[
"name": URL1,
"name": URL2
]
Use map(_:) to convert each element of the array to dictionary like so,
let arr = ["ABC","ZYZ","123"]
let result = arr.map { (element) -> [String:String] in
var dict = [String:String]()
dict["name"] = element
if let char = element.first {
dict["type"] = String(char)
}
return dict
}
print(result)
since you are concern about the index, my approach will be using enumerated() which gives out the index
let array = ["ABC","ZYZ","123"]
var results: [[String: String]] = []
for (i, content) in array.enumerated() {
let type: String = i == 0 ? "A" : "B"
results.append(["name": content, "type": type])
}
print(result)
// [["type": "A", "name": "ABC"], ["name": "ZYZ", "type": "B"], ["type": "B", "name": "123"]]

How To Display key and value from Json Object

I'm using Json Object to display in tableview.I parsed Json successfully print data also. and I'm using foreach statement to get the data into variable But the problem is I'm getting in variable the last item in json object. I want to display user to name variable to present name on it
here is my Json data
{
"Categories": [
"school, class"
],
"Tags": [
{
"Value": "ashok",
"Key": "Name"
}, {
"Value": "III",
"Key": "class"
}, {
"Value": "A",
"Key": "section"
}
]
}
here is my model array
struct classInfo: Decodable {
let Categories: String
let Tags: String
let Value: String
let Key: String
var Name: String
let class: String
}
here is my code
var ClassList = [classInfo]()
var name: String = ""
var class: String = ""
In JSONSerialization FUNCTION
do{
let json = try JSONSerialization.jsonObject(with: data!, options: []) as! [String: AnyObject]
print(json as AnyObject)
let cat = json["Categories"] as? [String: Any]
print(cat!)
if let array = json["Tags"] as? [[String: Any]] {
for obj in array {
if let dict = obj as? NSDictionary {
// Now reference the data you need using:
let Value = dict.value(forKey: "Value")
let Key = dict.value(forKey: "Key")
print(Value!)
print(Key!)
self.name = tag["Value"] as! String
print(self.name)
self.class = tag["Value"] as! String
print(self.class)
}
}
}
IN CELL FOR ROW FUNCTION
cell.Name.text = "Name:\(name)"
cell.class.text = "class: \(class)"
use this
class ModelClass{ var name:String ; var classs:String }
class ModelDataClass { static var modelData = [ModelClass]() }
in your viewController. - add values in models and
in you cellForRowAt -- >
cell.nameTextLabel.text = ModelDataClass.modelData[indexPath.row].name
cell.classsTextLabel.text = ModelDataClass.modelData[indexPath.row].classs
heyy , try this then ,
class ModelClass {var name:String}
now create a custom tableView cell
class CustomTableViewCell:UITableViewCell {
var dataModel : ModelClass?{
didSet{
guard let model = dataModel else {return}
print(model.name)
// set label text here : ex := myLabel.text = model.name
}
}
// declare all IBLayouts or create them programmatically... its your choice
}
in Your tableView cell (cellForRowAt ---> )
use this snippet
var dataModel = [ModelClass]()
dataModel = [ModelClass(name:"Rishabh"),ModelClass(name:"Adi"),ModelClass(name:"FFFf")]
now pass this dataModel to cellDAtaModel by using
let cell = tableView.deq() as! CustomTableViewCell //deq() - > to lazy to type whole lol ;P type by yourself
cell.dataModel = dataModel[indexPath.row]

How to append JSON values into array using Swift 4?

I am trying to get JSON values and appending into array. Here, below code add_user_product have a chance to come null. If it is null need to append null into array and if not null need to store ID also.
I am trying to get output like - [10,null,12,13,null,……]
// add_user_products & If add_user_product == null need to store null otherwise add_user_product ["id"]
if let add_user_product = fields[“add_user_product"] as? [String : Any] {
let add_id = add_user_product["id"] as! Int
self.addlistIDData.append(add_id)
}
else {
//print("Failure")
}
below my sample response
{
"students":[
{
"grade":0,
"add_user_product":
{
"id":10
}
},
{
"grade":1,
"add_user_product":null
},
{
"grade":2,
"add_user_product":
{
"id":11
}
}
]
}
Expected output: [10,null,11,......] //This array I am going to use Tableview cell
I suggest use nil instead of null string.
Declare your addlistIDData type as [Int?] where Int is an Optional.
Consider below example I have created for you:
var addlistIDData: [Int?] = [10, nil, 12, 13, nil] //Created array just for example
//created dict for testing purpose
let fields: [String : Any]? = ["add_user_product": ["id": nil]]
if let field = fields {
if let add_user_product = field["add_user_product"] as? [String:Any] {
let add_id = add_user_product["id"] as? Int
//now append your object here weather it's a nil or it has any value
addlistIDData.append(add_id)
}
}
else {
//print("Failure")
}
print(addlistIDData)
And output will be:
[Optional(10), nil, Optional(12), Optional(13), nil, nil]
PS: You need to cast an object with if let or with guard let whenever you are accessing objects from this addlistIDData array.
null will not be identifiable, the only way to store it in your array would be to store it as String, But for that also you'll have to store othere elements as String.
But i would suggest instead of adding null just add 0 as:
var arr = [Int]()
if let add_user_product = fields["add_user_product"] as? [String: Any] {
if let productId = add_user_product["id"] as? Int {
arr.append(productId)
} else {
arr.append(0)
}
} else {
//
}
You can do like this:
var resultArray = [Int?]()
if let add_user_product = fields["add_user_product"] as? [String: Any] {
if let add_id = add_user_product["id"] as? Int {
resultArray.append(add_id)
} else {
resultArray.append(nil)
}
} else {
//print("Failure")
}
Hope this Helps.
You can use compactMap:
let arrayDict = [ ["id" : 3], ["id" : nil], ["id" : 5] ]
let result = arrayDict.compactMap { $0["id"] }
print(result)
Output:
[Optional(3), nil, Optional(5)]

How to build a URL by using Dictionary in Swift

So I am messing around with the iMessages Framework, and in order to send data to another user the data must be sent as a URLComponents URL. However I can't figure out how to send a dictionary to use as the messages.url value.
func createMessage(data: dictionary) {
/*
The Dictionary has 3 values, 1 string and two arrays.
let dictionary = ["title" : "Title Of Dictionary", "Array1" : [String](), "Array2" : [String]() ] as [String : Any]
*/
let components = URLComponents()
let layout = MSMessageTemplateLayout()
layout.image = UIImage(named: "messages-layout.png")!
layout.imageTitle = "\(dictionary["title"])"
let message = MSMessage()
message.url = components.url!
message.layout = layout
self.activeConversation?.insert(message, completionHandler: { (error: Error?) in
print("Insert Message")
})
}
Does anybody know how I can send the dictionary values as URLQueryItems in the URLComponents to save as the message.url ?
PS: I was wondering wether it would be possible to create an extension for the URL to store the dictionary in, that is what I am unsuccessfully trying atm.
Here is a code snippet to convert dictionary to URLQueryItems:
let dictionary = [
"name": "Alice",
"age": "13"
]
func queryItems(dictionary: [String:String]) -> [URLQueryItem] {
return dictionary.map {
// Swift 3
// URLQueryItem(name: $0, value: $1)
// Swift 4
URLQueryItem(name: $0.0, value: $0.1)
}
}
var components = URLComponents()
components.queryItems = queryItems(dictionary: dictionary)
print(components.url!)
You can use the following URLComponents extension:
extension URLComponents{
var queryItemsDictionary : [String:Any]{
set (queryItemsDictionary){
self.queryItems = queryItemsDictionary.map {
URLQueryItem(name: $0, value: "\($1)")
}
}
get{
var params = [String: Any]()
return queryItems?.reduce([:], { (_, item) -> [String: Any] in
params[item.name] = item.value
return params
}) ?? [:]
}
}
}
And set the url components:
var url = URLComponents()
url.queryItemsDictionary = ["firstName" : "John",
"lastName" : "Appleseed"]
You can use iMessageDataKit library. It's a tiny, useful MSMessage extension for setting/getting Int, Bool, Float, Double, String and Array values for keys.
It makes setting and getting data really easy like:
let message: MSMessage = MSMessage()
message.md.set(value: 7, forKey: "user_id")
message.md.set(value: "john", forKey: "username")
message.md.set(values: ["joy", "smile"], forKey: "tags")
print(message.md.integer(forKey: "user_id")!)
print(message.md.string(forKey: "username")!)
print(message.md.values(forKey: "tags")!)
(Disclaimer: I'm the author of iMessageDataKit)

Resources