Post JSON request in Swift 3 - ios

I need to post JSON data that looks like this :
{ “orders”:[ {“id”: 208, “quantity”: 1 },{“id”: 212, “quantity”: 2},{“id”: 202, “quantity”: 5}, ...etc ],“HHStatus”: “1 }
I have the following variable :
var orders : [ShoppingCart] = []
that contains data as :
[Crash.ShoppingCart(drinkId: 743, drinkName: "aqua", drinkPrice: "2.26", drinkQuantity: 2), Crash.ShoppingCart(drinkId: 715, drinkName: "yellow", drinkPrice: "6.92", drinkQuantity: 1), Crash.ShoppingCart(drinkId: 738, drinkName: "blue", drinkPrice: "4.69", drinkQuantity: 2)]
...etc
I am able to post the request using :
for order in orders {
let orderId = order.drinkId
let orderQuantity = order.drinkQuantity
let parameters = ["orders": [["id": orderId, "quantity": orderQuantity]], "HHStatus": orderHHStatus!] as [String : Any]
let jsonData = try! JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
but then I want the whole order not just one id and one quantity,
and I have tried using :
let orderId = orders.map { $0.drinkId }
let orderQuantity = orders.map { $0.drinkQuantity }
let parameters = ["orders": [["id": orderId, "quantity": orderQuantity]], "HHStatus": orderHHStatus!] as [String : Any]
let jsonData = try! JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
but then I end up with something like this :
["HHStatus": "0", "orders": [["id": [743, 715, 738], "quantity": [2, 1, 2]]]]
How can I send all the ids and quantities in one request?
I can't figure out how to get something like :
["orders": [["id": orderId, "quantity": orderQuantity],["id": orderId, "quantity": orderQuantity], ["id": orderId, "quantity": orderQuantity]], "HHStatus": orderHHStatus!]
so many thanks for any help provided!

Map the ShoppingCart array to an array of dictionaries with the map function:
let mappedOrders = orders.map { ["id" : $0.drinkId, "quantity" : $0.drinkQuantity] }
Create the parameters dictionary
let parameters : [String:Any] = ["orders" : mappedOrders, "HHStatus" : orderHHStatus!]
Don't pass the .prettyPrinted option, the server doesn't care about aesthetics.
Omit the options parameter.

Related

How to post array of single value in alamofire?

I have to post json object.
One important thing, I have to post array of single value.
look at below code.
var pagingOption: [String: Any] = ["page": page,
"rowsPerPage": 20,
"sort": ["id": sortOption.rawValue,
"direction": "DESC"],
"searchStatues": ["accept"]]
searchStatuses is must array. But If I send this code, searchStatuses is not posted array.
If I add more value like this
var pagingOption: [String: Any] = ["page": page,
"rowsPerPage": 20,
"sort": ["id": sortOption.rawValue,
"direction": "DESC"],
"searchStatues": ["accept", "asdf", "asdf"]]
Then delivered array.
If I have only single value, How can I do that??
You can do it this way.
let searchValues: [String] = []
searchValues = ["accept", "asdf", "asdf"]
var pagingOption: [String: Any] = ["page": page,
"rowsPerPage": 20,
"sort": ["id": sortOption.rawValue,
"direction": "DESC"],
"searchStatues": searchValues]

Adding to dictionary dynamically

I 'm having an array of dictionary like so...
[
{
"id" : "3",
"sellingPrice" : "520",
"quantity" : "15"
},
{
"id" : "5",
"sellingPrice" : "499",
"quantity" : "-1"
},
{
"id" : "8",
"sellingPrice" : "500",
"quantity" : "79"
}
]
Now I want to add to the dictionary another key called remaining_balance with a value of 420,499 & 500 respectively. How can I achieve this..? Hope somebody can help...
It seems like you want to add a value to your dictionary that is an array:
var arrDict = Array<Dictionary<String,Any>>() //Your array
arrDict.append(["id":"3","sellingPrice":"520","quantity":"13"])
arrDict.append(["id":"5","sellingPrice":"43","quantity":"32"])
arrDict.append(["id":"8","sellingPrice":"43","quantity":"33"])
let arrValue = ["420","499","500"] //Your remaining value in array
print("Before ",arrDict)
for (index,dict) in arrDict.enumerated() {
var dictCopy = dict //assign to var variable
dictCopy["remaining_balance"] = arrValue[index]
arrDict[index] = dictCopy //Replace at index with new dictionary
}
print("After ",arrDict)
EDIT
If you are able keep an index of an array it would be possible,
Assuming that you have the index of an array
var dictCopy = arrDict[index]
dictCopy["remaining_balance"] = "666" //Your calculated value
arrDict[index] = dictCopy //Replace at index with new dictionary
var newKV = [["remaining_balance": "420"],["remaining_balance": "490"],["remaining_balance": "500"]]
let array = [["id":"3", "sellingPrice":"520", "quantity":"15"], ["id":"5", "sellingPrice":"520", "quantity":"15"], ["id":"8", "sellingPrice":"520", "quantity":"15"]]
let newArray = array.enumerated().map { (index : Int, value: [String: String]) -> [String: String] in
var dic = value
dic.merge(newKV[index]) { (_, new) -> String in
new
}
return dic
}
You could achieve it by mapping your array:
var myArray = [["id": "3", "sellingPrice": "520", "quantity" : "15"], ["id": "5", "sellingPrice": "499", "quantity" : "-1"], ["id": "8", "sellingPrice": "500", "quantity" : "79"]]
print(myArray)
/*
[["id": "3", "sellingPrice": "520", "quantity": "15"],
["id": "5", "sellingPrice": "499", "quantity": "-1"],
["id": "8", "sellingPrice": "500", "quantity": "79"]]
*/
print("___________________")
var remainingBalanceDesriedValue = 420
myArray = myArray.map { (dict: [String: String]) -> [String: String] in
var copyDict = dict
copyDict["remaining_balance"] = "\(remainingBalanceDesriedValue)"
remainingBalanceDesriedValue = (remainingBalanceDesriedValue == 420) ? 499 : (remainingBalanceDesriedValue == 499) ? 500 : 420
return copyDict
}
print(myArray)
/*
[["sellingPrice": "520", "quantity": "15", "id": "3", "remaining_balance": "420"],
["sellingPrice": "499", "quantity": "-1", "id": "5", "remaining_balance": "499"],
["sellingPrice": "500", "quantity": "79", "id": "8", "remaining_balance": "500"]]
*/
Let's assume you have an array of dictionaries like so:
var arrayOfDictionaries = [
[
"id": 3,
"sellingPrice": 520,
"quantity": 15
]
]
It is important that arrayOfDictionaries is not a let constant, otherwise it is considered immutable and you can not call append on it.
Now you init a new dictionary like:
let newDictionary = [
"id": 10,
"remaining_balance": 420,
"quantity": 15
]
Now add the newDictionary like
arrayOfDictionaries.append(newDictionary)
If the order is important
If the order is important there are a couple of ways to go about that.
When calling append the new value (in this case the new dictionary) will always be inserted at the bottom of the array.
If for some reason you can not call append in the correct order you could use insert, which inserts your dictionary at a specific position.
Yet another way is to append the values wildly and after you are done, call sort on the array.
Improvement Tips
Notice that for the values I did not use strings, as you only have numbers like "id" : 30.
Also, if you want the second key to be called remaining_balance you should call the first key selling_price instead of sellingPrice. Because of conistency.
Alternative approach
As far as I have understood you are trying to implement some software that is responsibly for selling some products.
I think you are tackling this problem from a completely wrong side.
I think you should read about database relationships. Selling products actually is a very common problem.
Maybe this will help you. I would offer a possible solution myself, but I think this misses the point of your question.
If you decide to use the database approach, you won't necessarily have to use a database. You can take the approach and implement it using simple structs/classes/arrays.
I noticed this question lacks an extension answer, yes.. I'm gonna be that guy, so here it is. This could be made more generic by supporting other types of dictionaries, feel free to pitch in ;)
Inspiration from #eason's answer.
var newKV = [["remaining_balance": "420"],["remaining_balance": "490"],["remaining_balance": "500"]]
var array = [["id":"3", "sellingPrice":"520", "quantity":"15"], ["id":"5", "sellingPrice":"520", "quantity":"15"], ["id":"8", "sellingPrice":"520", "quantity":"15"]]
extension Array where Element == [String: String] {
enum UniquingKeysStrategy {
case old
case new
}
mutating func merge(with target: Array<Element>, uniquingKeysWith: UniquingKeysStrategy = .new) {
self = self.merged(with: target)
}
func merged(with target: Array<Element>, uniquingKeysWith strategy: UniquingKeysStrategy = .new) -> Array<Element> {
let base = self.count > target.count ? self : target
let data = self.count > target.count ? target : self
return data.enumerated().reduce(into: base, {
result, data in
result[data.offset]
.merge(data.element, uniquingKeysWith: {
old, new in
if strategy == .new { return new }
return old
})
})
}
}
let mergedArrays = newKV.merged(with: array, uniquingKeysWith: .old)
array.merge(with: newKV)
Happy Coding :)

Swift Create Json for API REST

I need create a json for send from a API REST:
{
"ownId": "seu_identificador_proprio",
"amount": {
"currency": "BRL",
"subtotals": {
"shipping": 1000
}
},
"items": [
{
"product": "Descrição do pedido",
"quantity": 1,
"detail": "Mais info...",
"price": 1000
}
],
"customer": {
"ownId": "seu_identificador_proprio_de_cliente",
"fullname": "Jose Silva",
"email": "nome#email.com",
"birthDate": "1988-12-30",
"taxDocument": {
"type": "CPF",
"number": "22222222222"
},
"phone": {
"countryCode": "55",
"areaCode": "11",
"number": "66778899"
},
"shippingAddress": {
"street": "Avenida Faria Lima",
"streetNumber": 2927,
"complement": 8,
"district": "Itaim",
"city": "Sao Paulo",
"state": "SP",
"country": "BRA",
"zipCode": "01234000"
}
}
}
I am confused with the creation..
I try begin with [NSObject:AnyObject]
var d1 : [NSObject:AnyObject] = ["ownId":"seu_identificador_proprio", "customer":""]
let dd1 = ["currency":"BRL"]
let dd2 = ["shipping":"1000"]
let arr = [d1]
let d = try! NSJSONSerialization.dataWithJSONObject(arr, options: NSJSONWritingOptions.PrettyPrinted)
let s = NSString(data: d, encoding: NSUTF8StringEncoding)! as String
print(s)
But I need help!
I have updated your code and added some hints, how can you build the above listed structure. Happy coding!
// Do not use NSObject as key's type
// Keys in a dictionary are usually Strig in every language
var d1: [String: AnyObject] = ["ownId":"seu_identificador_proprio", "customer":""]
// Define the type of your dictionaries, if you dont, in this case it will create a [String:String] dictionary, but you need to insert an array into it
// Make it a var, so you can mutate the container
var dd1: [String: AnyObject] = ["currency":"BRL"]
// Here the type is undefined. Try inserting anything else than String, and see the results
let dd2 = ["shipping":"1000"]
dd1["subtotals"] = dd2
d1["amount"] = dd1
// Build all your dictionaries like i did above, and at the end add all of them into arr
let arr = [d1]
// Do not force try any throwing function in swift - if there is an error, your application will crash
// Use proper error handling - https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html
do {
let d = try NSJSONSerialization.dataWithJSONObject(arr, options: NSJSONWritingOptions.PrettyPrinted)
let s = NSString(data: d, encoding: NSUTF8StringEncoding)! as String
print(s)
} catch {
// Do your error handling here
}

Sort array of objects based on values in another array that correspond to specific properties

Let's say retrieve an array of objects from a JSON API:
[
{
"id": 48,
"name": "Bob"
},
{
"id": 198,
"name": "Dave"
},
{
"id": 2301,
"name": "Amy"
},
{
"id": 990,
"name": "Colette"
}
]
// e.g. for ease of reproduction:
let dataObjects = [
["id": 48, "name": "Bob"],
["id": 198, "name": "Dave"],
["id": 2301, "name": "Amy"],
["id": 990, "name": "Colette"]
]
On the client, I'd like to allow the user to re-order these objects. To save the order, I'll store a list of ids in an array:
let index: [Int] = [48, 990, 2103, 198]
How can I reorder the original array of data objects based on the order of ids in the sorting index?
dataObjects.sort({
// magic happens here maybe?
}
So that in the end, I get:
print(dataObjects)
/*
[
["id": 48, "name": "Bob"],
["id": 990, "name": "Colette"],
["id": 2301, "name": "Amy"],
["id": 198, "name": "Dave"]
]
/*
Approach A) Parsing the data into a simple dictionary where the key for the dictionary is the id used to sort it:
func sort<Value>(a: [Int: Value], basedOn b: [Int]) -> [(Int, Value)] {
return a.sort { x, y in
b.indexOf(x.0) < b.indexOf(y.0)
}
}
// ....
let a = [48:"Bob", 198:"Dave", 2301:"Amy", 990:"Colette"]
let b = [48, 198, 2301, 990]
sort(a, basedOn: b)
Approach B) With some custom DataObject type: (probably best way)
struct DataObject {
let id: Int
let name: String
init(_ id: Int, _ name: String) {
self.id = id
self.name = name
}
}
func sort(a: [DataObject], basedOn b: [Int]) -> [DataObject] {
return a.sort { x, y in
b.indexOf(x.id) < b.indexOf(y.id)
}
}
let a = [DataObject(48, "Bob"), DataObject(198, "Dave"), DataObject(2301, "Amy"), DataObject(990, "Colette")]
let b = [48, 198, 2301, 990]
sort(a, basedOn: b)
/* [
DataObject(id: 48, name: "Bob"),
DataObject(id: 990, name: "Colette"),
DataObject(id: 198, name: "Dave"),
DataObject(id: 2301, name: "Amy")
] */
Approach C) With the raw json values, it can be done in a less "clean" way:
func sort<Value>(a: [[String: Value]], basedOn b: [Int]) -> [[String: Value]] {
return a.sort { x, y in
let xId = x["id"] as! Int
let yId = y["id"] as! Int
return b.indexOf(xId) < b.indexOf(yId)
}
}
let dataObjects = [
["id": 48, "name": "Bob"],
["id": 198, "name": "Dave"],
["id": 2301, "name": "Amy"],
["id": 990, "name": "Colette"]
]
let b = [48, 198, 2301, 990]
sort(dataObjects, basedOn: b)
You could benefit of the functional support that Swift has, and use the map function to iterate over the index array and get the corresponding object:
let sortedObjects = index.map{ id in
dataObjects.filter{ $0["id"] as? Int == id }.first
}
This assumes that the index array is correctly computed before mapping the data objects.
Edit
Thanks to user3441734 for the flatMap suggestion. Here's a solution that makes use of it, basically it simply replaced map by flatMap in order to get rid of the possible nil values in the mapped array, and to convert the resulting array into an array of non-optionals.
let sortedObjects = index.flatMap{ id in
dataObjects.filter{ $0["id"] as? Int == id }.first
}
If an empty index should result in the same order being kept, then we can simply test for that:
let sortedObjects = index.count > 0 ? index.flatMap{ id in
dataObjects.filter{ $0["id"] as? Int == id }.first
} : dataObjects
You don't need to keep an array with the index you can sort by the object you want, let's says you have the following structure:
struct DataObject {
var id: Int
var name: String
}
var data = [DataObject]()
data.append(DataObject(id: 48, name: "Bob"))
data.append(DataObject(id: 198, name: "Dave"))
data.append(DataObject(id: 2301, name: "Amy"))
data.append(DataObject(id: 990, name: "Colette"))
The you can use the sort function to sort and return the result in other array or just the sorted function if you want to make it in-place
// ordered by id
var sortedData = data.sort { index.indexOf($0.id) < index.indexOf($1.id) }
I hope this help you.

Create a particular JSON Structure in Swift

I'm having trouble creating a specific structure in JSON with Swift. I use Swifty JSON for parsing but I can't figure out how to create one.
I have this array which is filled by Id's and quantity Ints of products in a shopping basket . I need to get the array into my JSON but I don't know how.
If you could help me with this I would be very glad :)
var productArray = Array<(id: Int,quantity: Int)>()
let jsonObject: [String: AnyObject] = [
"order": 1,
"client" : 1,
"plats": [
for product in productArray
{
"id": product.id
"quantity": product.quantity
}
]
]
You can't just start looping through stuff while defining your dictionary. Here's another approach.
First, create your array:
var productArray = Array<(id: Int,quantity: Int)>()
Add some products (for testing):
productArray += [(123, 1000)]
productArray += [(456, 50)]
Map this array into a new array of dictionaries:
let productDictArray = productArray.map { (product) -> [String : Int] in
[
"id": product.id,
"quantity": product.quantity
]
}
Use the new mapped array in your JSON object:
let jsonObject: [String: AnyObject] = [
"order": 1,
"client" : 1,
"plats": productDictArray
]
You are not supposed to do any kind of looping/condition making block of codes while creating Array's or Dictionary. For that you need to execute that piece of code outside, create a variable and use it.
Do try this way.
var productArray = Array<(id: Int,quantity: Int)>()
var prods = [[String:Int]]()
for product in productArray
{
var eachDict = [String:Int]()
eachDict["id"] = product.id
eachDict["quantity"] = product.quantity
prods.append(eachDict)
}
let jsonObject: [String: AnyObject] = [
"order": 1,
"client" : 1,
"plats": prods
]

Resources