How to convert model with array to JSON array Swift 3 - arrays

i have some question and solution, i have class model and it has array inside, my model like this
class WillModel{
var name: String = ""
var documents:[WillItems] = []
var isLFStatus : Bool = false
var isLFShared : Bool = false
}
class WillItems{
var documentPath: String = ""
var documentRemark: String = ""
}
i want to convert the result to JSON Array like
{
"name" : "value",
"documents" : [
{
"documentPath" : "value"
"documentRemark" : "value"
},
{
"documentPath" : "value2"
"documentRemark" : "value2"
}
],
"isLFStatus" : true,
"isLFShared" : true
}
i'm using Swift 3, thanks for your solutions

You can write a simple method to manually encode your model to json as below,
func encodeWillModel(_ model: WillModel) -> [String: Any] {
var params: [String: Any] = [:]
params["name"] = model.name
params["documents"] = model.documents.map({["documentPath": $0.documentPath,
"documentRemark": $0.documentRemark]})
params["isLFStatus"] = model.isLFStatus
params["isLFShared"] = model.isLFShared
return params
}
and you can pass any model to get the json something like,
let willModelJSON = encodeWillModel(yourModel)
But a better approach would be to use any json parsing library(SwiftyJSON, ObjectMapper) that supports Swift 3 or upgrade to Swift 4 and use Encodable/Decodable

Related

iOS How To Convert Dictionary<String, Any> to query params which containing array

I Have a Dictionary Data:
let dict: [String: Any] = [
"shapeIDs": [1,2,3],
"rows": [1,2],
"userID": "231"
]
I want to convert it in query params for URL. My Expect Result should be this:
"?shapeIDs[]=1&shapeIDs[]=2&shapeIDs[]=3&rows[]=1&rows[]=2&userID=231"
Please help to create an optimistic logic for this.
Swift Solution:
extension Dictionary {
var queryString: String {
let query = self.reduce("") { (result, keyValue) -> String in
var string = ""
if let values = keyValue.value as? Array<Any> {
string = values.map({"\(keyValue.key)[]=\($0)&"}).reduce("", +)
} else {
string = "\(keyValue.key)=\(keyValue.value)&"
}
return result + string
}.dropLast()
return "?" + String(query)
}
}

swift send array to web service parameters

I want to send array object to web service, but when I try to add array to parameters it gives error. I tried many things but nothing found usefully.
I want to add ("assignees" : newList) in parameter and than send it to web service
Here is my code
var newList = [Assignee]()
var assignee = Assignee()
for u in task.NewWorkList! {
assignee = Assignee()
assignee.assignedEmail = u.Email
assignee.assignedName = u.Name
assignee.assignedSurname = u.Surname
assignee.assignedType = "PERSONEL"
assignee.assignedTo = String(u.Id!)
newList.append(assignee)
}
// in this part newList is an array of assignees.
var assigneeListString = ""
let jsonEncoder = JSONEncoder()
do {
let jsonData = try jsonEncoder.encode(newList)
assigneeListString = String(data: jsonData, encoding: .utf8)!
print("assigneeListString:",assigneeListString)
} catch {
print("error:::")
}
var parameters = [
"taskType" :
[
"code" : "OTHER"
],
"complateButtons": "COMPLATE",
"assignees" : [JSON(assigneeListString)], // does not work
// "assignees" : [JSON(newList)], // does not work
// "assignees" : JSON(newList), // does not work
// "assignees" : newList, // does not work
// "assignees" : assigneeListString, // does not work
"repeatTimeType":"NEVER"
] as [String : Any]
print("parameters:",parameters)
DAL.Service.MakeRequest(url: Constants.Service.Url.newTask,
parameters : parameters,
httpMethod : ServiceMethods.post.rawValue,
resultFunc: serviceResultFunc)
when I print parameters assignee section adds extra semi colon,
[[{"assignedTo":"63659","assignedSurname":"DAVID","assignedType":"PERSONEL","assignedName":"JOE","assignedEmail":"joe#abc.com"},{"assignedTo":"21026","assignedSurname":"GEORGE","assignedType":"PERSONEL","assignedName":"MICHAEL","assignedEmail":"michael#abc.com"}]],
when I manually add assignees to patameters , its ok.
[["assignedTo":"63659","assignedSurname":"DAVID","assignedType":"PERSONEL","assignedName":"JOE","assignedEmail":"joe#abc.com"},{"assignedTo":"21026","assignedSurname":"GEORGE","assignedType":"PERSONEL","assignedName":"MICHAEL","assignedEmail":"michael#abc.com"]],
I solved the problem with below code:
var assigneesList = [[String:Any]]()
for a in task.YeniGorevAtamaList! {
assigneesList.append(
["assignedTo":(a.Id) ?? "0",
"assignedSurname":a.Surname ?? "",
"assignedType":a.assignedType ?? "PERSONEL",
"assignedName":a.Name ?? "",
"assignedEmail":a.Email as Any
]
);
}
let parameters = [
"taskType" :
[
"code" : "DIGER"
],
"assignees" : assigneesList ,
"taskUrls" :
[
]
] as [String : Any]

Array of JSON .count always returns 0 in Swift 4

I got some issues with JSON in swift. When I get JSON data from userDefault storage (Array of JSON as String format) then parse it into JSON object and count number of object in array, but the result always return O (Zero).
My swift code:
let carts = userStorage.object(forKey: userDefaultKeys.carts)
print("logging carts....")
print(JSON(carts as! String).count)
print(JSON(carts as! String))
And it logged into result window
logging carts....
0
[
{
"Lat" : 32,
"Time" : null,
"Items" : [
{
"StorePhone" : "018753678474",
"Ingredient" : "",
"FK_Category" : 2,
"Enabled" : 1,
"UpdatedAt" : null,
"IsActive" : 1,
"quantity" : 1,
}
],
"DeliveryFee" : null,
"Photos" : "https:\/\/networkposting.com\/wpcontent\/uploads\/2018\/02\/maxresdefaul-137.jpg"
}
]
As per the Usage Documentation on the GitHub page:
Initialization
let json = JSON(data: dataFromNetworking)
or
let json = JSON(jsonObject)
or
if let dataFromString = jsonString.data(using: .utf8, allowLossyConversion: false) {
let json = JSON(data: dataFromString)
}
So you can't init a SwiftyJSON object directly via String like you are.
If you have a JSON String... Use the bottom example above to convert it to data first.

Swift 4 filter json array into sub arrays

I got this code:
let arrData = [["id": "1",
"name": "Apple",
"category": "Fruit"],
["id": "2",
"name": "Pie",
"category": "Fruit"],
["id": "3",
"name": "Tomato",
"category": "Vegetable"]]
let categorieNames = Array(Set(arrData.map({$0["category"]!})))
var arrResult:[[String]] = []
for i in 0..<categorieNames.count {
let categories = arrData.filter({$0["category"] == categorieNames[i]}).map({$0["name"]!})
arrResult.append(categories)
}
print("result : \(arrResult)")
it works perfectly with an Array.
But now I get my data from a json:
[{"id":"1",
"name":"Apple",
"category":"Fruits"},
{"id":"2",
"name":"Pie",
"category":"Fruits"},
{"id":"3",
"name":"Tomato",
"category":"Vegetable"}]
here is my struct and my decode function:
struct MarketStruct : Decodable {
let id : Int?
let name : String?
let category : String?
}
class MarketsCollectionViewController: UICollectionViewController, NetworkDelegate {
var myMarkets : [MarketStruct]?
var categorieNames : [Any] = []
var categorieArray:[[String]] = []
func didFinish(result: Data) {
do {
self.myMarkets = try JSONDecoder().decode([MarketStruct].self, from: result)
categorieNames = Array(Set(myMarkets!.map({ ["category": $0] })))
for i in 0..<categorieNames.count {
let categories = myMarkets!.filter({$0["category"] == categorieNames[i]}).map({["name": $0]!})
categorieArray.append(categories)
}
} catch let jsonErr {
print("Error:", jsonErr)
}
self.myCollectionView.reloadData()
}
I got an error at the filter part:
Type 'MarketStruct' has no subscript members
what must I change that the above Array code works with my JSON array?
thanks for your help.
edit my current code:
self.myMarkets = try JSONDecoder().decode([MarketStruct].self, from: result)
categorieNames = Array(Set(myMarkets.map({$0.category })))
for i in 0..<categorieNames.count {
let categories = myMarkets!.filter({$0.category == categorieNames[i]}).map({$0.name})
categorieArray.append(categories as! [String])
}
} catch let jsonErr {
print("Error:", jsonErr)
}
self.myCollectionView.reloadData()
it compiles with error: Command failed due to signal: Segmentation fault: 11
if I comment categorieNames = Array(Set(myMarkets.map({$0.category }))) out it compiles without errors
You are getting the compiler error because the category property is optional and therefore does not conform to Hashable.
Set requires that all elements conform to that.
One way to get around that is to use flatMap instead of map, which has the added capability of filtering out the nil values.
categorieNames = Array(Set(myMarkets.flatMap({$0.category })))
There are a lot of issues in the code
In the JSON the type of id is String not Int
The members in the struct are supposed to be non-optional.
The categorieNames array is supposed to be specific [String], not unspecified [Any]
In the filter line access the category by dot notation, not key subscription (Error 1)
Rather than declaring myMarkets as optional, initialize it as an empty array (Error 2)
Don't use ugly index-based for loop, use fast enumeration (not really an issue)
And why do you map myMarkets to an array of dictionaries?
struct MarketStruct : Decodable {
let id : String
let name : String
let category : String
}
var myMarkets = [MarketStruct]()
var categorieNames = [String]()
var categorieArray = [[String]]()
let jsonString = """
[{"id":"1", "name":"Apple", "category":"Fruits"},
{"id":"2", "name":"Pie", "category":"Fruits"},
{"id":"3", "name":"Tomato", "category":"Vegetable"}]
"""
let data = Data(jsonString.utf8)
do {
myMarkets = try JSONDecoder().decode([MarketStruct].self, from: data)
let categorieNames = Array(Set(myMarkets.map { $0.category }))
for categoryName in categorieNames {
let categories = myMarkets.filter({$0.category == categoryName}).map({$0.name})
categorieArray.append(categories)
}
print(categorieArray)
} catch { print(error) }

Appending to Array in Deeply Nested Dictionary of Arrays

I am having the following problem in Swift. First, I declare a data structure, like this:
var books = [String : Dictionary<String, Dictionary<String, Dictionary<String, Array<Dictionary<String, String>>>>>]()
I later initialize the var like this:
books = [
"Fiction" : [
"Genre Fiction" : [
"Mystery" : [
"Classics" : [
["Title" : "Ten Little Indians",
"Author" : "Agatha Christie",
"read" : "no"],
["Title" : "A Study in Scarlet",
"Author" : "Arthur Conan Doyle",
"read" : "no"],
]
]
]
]
]
Note that the compiler does not complain about it. Later, I create a new dictionary which I would like to append to that innermost array, like this:
var bookDict = Dictionary<String, String>()
bookDict = ["title" : dict.valueForKey("title") as! String,
"author": dict.valueForKey("author") as! String,
"read" : dict.valueForKey("read") as! String ]
books["category"]["genre"]["focus"]["set"].append(bookDict)
However, I get a compiler error that "Cannot invoke append with an argument list of type (Dictionary < String, String>)". This is confusing to me because the books data structure is declared such that that innermost array is an array of Dictionary< String, String>.
What am I missing?
It's not clear during compile time if the key is really present in the dictionary so dictionaries always return optional values. You have to check this optionals:
if let category = books["Fiction"] {
if let genre = category["Genre Fiction"] {
if let focus = genre["Mystery"] {
if var set = focus["Classics"] {
set.append(bookDict)
}
}
}
}
Or you can do it also like this:
books["Fiction"]?["Genre Fiction"]?["Mystery"]?["Classics"]?.append(bookDict)

Resources