iterate JSON, swift - ios

I am working on swift.
The response that I get from the web server is different when i test it on Postman/ browser and mobile emulator.
Postman/browser response :
items: [
{
itemId: 500,
name: "ABC"
},
{
itemId: 500,
name: "ABC"
}
]
Response in iOS :
items: (
{
itemId: 500,
name: "ABC"
},
{
itemId: 500,
name: "ABC"
}
)
I would like to know how to iterate through the array, but since the result is not an array on iOS I am not sure on how should I go about it. Also, I retrieve a result of around 25-30 items in the array. I have a some set of variables too, that are provided in the response after the array.

There is no problem with your response in ios when you print an array it will print with () brackets instead of [] brackets and dictionary will be print with {} braces.
As you say let items : [NSDictionary]! your items array contain dictionary then you can iterate it like this
for item in items {
print(item["itemId"])
print(item["name"])
}

As others have said, your response in iOS is fine.
You can iterate over it simply with:
for item in items {
// do what you want with each item
}
It works fine in a Playground:
let items = [["itemId": 500, "name" : "ABC"], [ "itemId": 500, "name": "ABC"]] as NSArray
for item in items {
print(item as! NSDictionary) // prints each dictionary as expected
}

You have an array of dictionaries. So, you can iterate like-
for itemDict in items {
let itemId = itemDict["itemId"]
println("Item ID: \(itemId)")
let name = itemDict["name"]
println("Item name: \(name)")
}

Related

Filter dictionary of array objects

I am trying to filter my dictionary according to user input in UISearchController. I have following model and array of objects.
struct People {
var name: String
var id: Int
}
let first = People(name: "Atalay", id: 1)
let second = People(name: "Ahmet", id: 2)
let third = People(name: "Mehmet", id: 3)
let fourth = People(name: "Yusuf", id: 4)
let peoples: [People] = [first, second, third, fourth, fifth]
I put them into a dictionary to create section indexed table view with following code.
var dict: [String: [People]] = Dictionary(grouping: peoples, by: { (people) -> String in
return String(people.name.prefix(1))
})
Above code gives me a dictionary with first letter of People names. Now, I would like to filter my array according to user input. However, I tried following code for filtering but it is not working as I expected.
let filteredDict = (dict.filter { $0.1.contains { $0.name.lowercased().contains("ata") } })
It returns all "A" letter section indexes like ["A": People(name: "Atalay", id: 1), People(name: "Ahmet", id: 2)]
How can I achieve filter also my array inside dictionary?
If I'm not mistaken, you want your final dictionary to have all the keys and only the filtered array of items as the values. If that is right, reduce is the tool for that:
let filtered = dict.reduce(into: [String: [People]]()) {
$0[$1.key] = $1.value.filter { $0.name.lowercased().contains("ata") }
}
I decided it was simplest to get this right by using an old fashioned for loop and filter each group separately
var filtered = [String: [People]]()
for (k, v) in dict {
let result = v.filter {$0.name.lowercased().contains("ata")}
if result.count > 0 {
filtered[k] = result
}
}
Note that if you want to keep all the groups in the result dictionary just skip the if result.count > 0 condition
How can I achieve filter also my array inside dictionary?
You should have an array first, you can use flatMap to group all the values in your filteredDict
let array = filteredDict.flatMap { $0.value }
Then you just filter the array as usually
let filteredArray = array.filter { $0.name.lowercased().contains("ata") }

swift parse json as per maintaining order

Suppose i have json string in which there is a json array called data.
The array holds json object of user profile data for example name,age,gender etc.
Now want to parse that json object as per order, for example if the object is
{
"name": "sample name",
"age": "30",
"gender": "male"
}
i want to parse the list as ordered like name,age,gender but with ios,when i convert the json object as dictionary , the order is changed,i know dictionary is not ordered so what is the the alternative to achieve this?
its a third party api so i dont have any hand on it,we have done it in android with linked hash map,but really stuck in swift , the last thing i would want to do is parse with regular expression.
im parsing the json in following way :
var rootData = try JSONSerialization.jsonObject(with: data!) as! [String:Any]
if let val = fromList["data"] {
let dataNode = val as! [[String:Any]]
for row in dataNode {
for (key,keyVal) in row {
//here the key is not in order.because when we cast it as dictionary the order gets changed.
}
}
For android we have achieved to do this with following function :
public ArrayList<LinkedHashMap<String, Object>> parseJsonArrayList(String odata, String arrayName) {
ArrayList<LinkedHashMap<String, Object>> mylist = new ArrayList<>();
try {
JSONObject e = new JSONObject(odata);
JSONArray data = e.getJSONArray(arrayName);
for(int i = 0; i < data.length(); ++i) {
JSONObject v = data.getJSONObject(i);
LinkedHashMap<String, Object> map = new LinkedHashMap<>(100, 0.75f, false);
Iterator keys = v.keys();
while(keys.hasNext()) {
String key = String.valueOf(keys.next());
//gph.log("debug4", key);
map.put(key, v.getString(key));
//gph.log("debug4", v.getString(key));
}
mylist.add(map);
}
} catch (JSONException var10) {
var10.printStackTrace();
}
return mylist;
}
Don’t try to order the dictionary. Instead create an array of the keys in the order you desire:
let keys = [“name”, “age”, “gender”]
Then access the dictionary with them:
for key in keys {
let value = dict[key]
// Present the value.
}
That will ensure the order you expect.
As you mentioned you cannot get the ordered data in Dictionary. If possible you can add the "order" key in your JSON like
[
{
"name": "sample name",
"order": 1
},
{
"age": "30",
"order": 1
},
{
"gender": "",
"male": "",
"order": 1
}
]
so that based on the order key you can do the sorting.

Taking out array from dictionary in swift 3

Hi I am trying to populate a view using the response obtained from service but not able to fetch the exact value out of the whole response ,
[
["product_id": PRO161519,
"name": clothes,
"brand_name": Levis,
"discountprice": 0,
"images": <__NSArrayM 0x6000002541c0>(
{
image = "HTTP://i.vinove.com/dnn/backend/uploads/954tshirt_PNG5434.png";
}
)
"category": Accessories,
"price": 23.00
]
]
ProductList-Model
import UIKit
import SpeedLog
let KImages = "images"
let KListImage = "image"
struct ProductList{
var images = ""
var itemArray = [String]()
func bindProductListDataToPopulateView(_ response:[[String:Any]])->[ProductList]{
SpeedLog.print("response value as result",response)
for items in response{
print("items values",items)
}
print("item array",itemArray)
return []
}
}
response value as result
[["image":
item Values
["image":
Kindly help me to get the values images here.
You have to use like this :
for product in products {
if let productImages = product["images"], let images = productImages as? NSArray {
for image in images {
if let image = image as? [String: String] {
print(image["image"])
}
}
}
}
More than likely that JSON response you posted will eventually find its way to you in the form of a key-value Dictionary. You then use a "key" from the JSON you posted to extract the key's corresponding "value". In the snippet you posted, the keys would be the values on the left of the colon (e.g. "product_id", "name", etc).
Now, lets say your dictionary of key-values was called "jsonDictionary". You then would extract the values like so:
let productId = jsonDictionary["product_id"]
let name = jsonDictionary["name"]
If, however, you don't have logic to deserialize that raw JSON data (that you posted in your question) into a Dictionary, then you'll have to start there instead.

Swift - Update an array of NSDictionary with values from another NSDictionary

Basically, I have an NSarray of dictionaries coming as a JSON response only once when view appears. Now, I need to update a particular value of a key in those dictionaries with another set of dictionary coming separately in every few second such that I can update my array of dictionaries continuously with those values and show some realtime set of data on the screen.
Example: This is the array of dictionary I am getting from backend
[
{item_id: 1001, name: "Apple", current_price: "$10"},
{item_id: 1009, name: "Orange", current_price: "$15"},
{item_id: 1004, name: "Mango", current_price: "$5"}
]
Current price is something which varies continuously, whose data I am receiving in NSDictionary format separately.
["1009": "$16", "1004": "$3", "1001": "$11"]
As you can see the new NSDictionary is mapped with the item_id to the current price value.
I need a way out to make sure the current price gets updated from this NSDictionary to the array of dictionary so that I can reuse that array to reload my UITableview and show the updated realtime price.
You can do it like this:
let items = [["item_id": 1001, "name": "Apple", "current_price": "$10"], ["item_id": 1009, "name": "Orange", "current_price": "$15"], ["item_id": 1004, "name": "Mango", "current_price": "$5"]]
let prices = ["1009": "$16", "1004": "$3", "1001": "$11"]
let updatedItems = items.map { itemDict -> [String: Any] in
var updatedItem = itemDict
if let idKey = itemDict["item_id"] as? Int {
prices["\(idKey)"].flatMap { updatedItem["current_price"] = $0 }
}
return updatedItem
}

SwiftyJSON keeps returning empty objects

I am new to SwiftyJSON, and I'm having some trouble with it. I can get it to return the entire JSON file as a string, but the moment I try to parse it, I keep getting empty variables back, and I'm not sure what I'm doing wrong.
This is the formatting of my JSON file:
[
{
"entryID": 1,
"from": "String",
"to": "String",
"value": "String"
},
{
...
},
...
]
And this is roughly what I want to do with it (in quite inelegant code, I do apologise, I'm new to Swift):
for entry: JSON in indexJSON.arrayValue {
var vEntryID: Int
var vFrom: String
var vTo: String
var vValue: String
for (dictKey: String, dictVal: JSON) in entry.dictionaryValue {
if(dictKey=="entryID") {vEntryID = dictVal.intValue}
if(dictKey=="from") {vFrom = dictVal.stringValue}
if(dictKey=="to") {vTo = dictVal.stringValue}
if(dictKey=="value") {vValue = dictVal.stringValue}
}
someSwiftObject[vEntryID]["from"] = vFrom
someSwiftObject[vEntryID]["to"] = vTo
someSwiftObject[vEntryID]["value"] = vValue
}
However, this block never executes at all, because indexJSON.arrayValue is always empty.
When I try to run the following, it correctly prints the complete file contents to the console:
let indexJSON = JSON(content!)
println(indexJSON.stringValue)
But when I try to go deeper, to fetch any element, it returns nothing:
if(indexJSON.arrayValue.isEmpty==true) {println("indexJSON.arrayValue is Empty")}
if(indexJSON[0].arrayValue.isEmpty==true) {println("indexJSON[0].arrayValue is Empty")}
if(indexJSON[0].dictionaryValue.isEmpty==true) {println("indexJSON[0].dictionaryValue is Empty")}
if(indexJSON[0]["entryID"]==nil) {println("indexJSON[0][\"entryID\"].stringValue is Empty")}
Output:
indexJSON.arrayValue is Empty
indexJSON[0].arrayValue is Empty
indexJSON[0].dictionaryValue is Empty
indexJSON[0]["entryID"].stringValue is Empty
I'd be grateful for any help! What am I doing wrong?
I checked SwiftyJSON source code and I think I know where the problem is.
I suppose that you are using String to initialize the JSON object like this
let s = "{\"entryID\": 1,\"from\": \"String\",\"to\": \"String\",\"value\": \"String\"}"
let j = JSON(s)
In this case the JSON object is actuall given a type "String", not Array. That's why it's not iterable and its arrayValue is empty.
To do what you want to do, you need to initialize it with an Array object:
let arr = [
[
"entryID":1,
"from":"String",
"to":"String",
"value":"String",
]
]
let j2 = JSON(arr)
Now j2 is an array JSON object and iterable.
SwiftyJSON can only be initialized with NSData and object. So if you want to initialize it with a String you need to do this:
if let data = s.dataUsingEncoding(NSUTF8StringEncoding) {
let j = JSON(data:data)
println(j)
}
first of all, make sure the format of your json string is correct. in your question, your json string is a array, just format the string like this(the content is from my code):
let jsonStr = "[{\"name\": \"hangge\", \"age\": 100, \"phones\": [{\"name\": \"公司\",\"number\": \"123456\"}, {\"name\": \"家庭\",\"number\": \"001\"}]}, {\"name\": \"big boss\",\"age\": 1,\"phones\": [{ \"name\": \"公司\",\"number\": \"111111\"}]}]"
then you can use SwityJson to get the array object, like this:
let strData = jsonStr.data(using: String.Encoding.utf8, allowLossyConversion: false)
let json = JSON(data: strData!)
for object in json.arrayValue {
let name = object["name"].string
}
Take a look at the documentation here: https://github.com/lingoer/SwiftyJSON#loop
You are iterating it incorrectly. You should be iterating over the array with a for loop like this:
for (index: String, subJson: JSON) in json {
//Do something you want
}

Resources