SwiftyJSON Append new data to existing JSON array - arrays

I am working on a way to add new JSON data to my existing JSON array:
var resources: JSON = [
"resources": []
]
override func viewDidLoad() {
super.viewDidLoad()
getApiResourceA() { responseObject, error in
var resourceA: JSON = [
"resourceA": []
]
let resourceAResponseObject = JSON(responseObject!)
resourceA["resourceA"] = resourceAResponseObject
self.resources["resources"] = resourceA
}
getApiResourceB() { responseObject, error in
var resourceB: JSON = [
"resourceB": []
]
let resourceBResponseObject = JSON(responseObject!)
resourceB["resourceB"] = resourceBResponseObject
self.resources["resources"] = resourceB
}
}
The structure I am trying to get is:
{
"resources": {
"resourceA": {
"id": 1
"name": "Name1"
}
"resourceB": {
"id": 2
"name": "Name2"
}
}
}
But in my code there are two different "resources"-array created...
Anyone know how to deal with this?

First it is important to understand that JSON is Struct means it is duplicated every time you pass it or use it.
Another issue, you declared resources as Array and not as Dictionary means you can use resource as key.
Declare extensions:
extension JSON{
mutating func appendIfArray(json:JSON){
if var arr = self.array{
arr.append(json)
self = JSON(arr);
}
}
mutating func appendIfDictionary(key:String,json:JSON){
if var dict = self.dictionary{
dict[key] = json;
self = JSON(dict);
}
}
}
use:
//notice the change [String:AnyObject]
var resources: JSON = [
"resources": [String:AnyObject](),
]
resources["resources"].appendIfDictionary("resourceA", json: JSON(["key1":"value1"]))
resources["resources"].appendIfDictionary("resourceB", json: JSON(["key2":"value2"]))
result:
{
"resources" : {
"resourceB" : {
"key2" : "value2"
},
"resourceA" : {
"key1" : "value1"
}
}
}

#daniel-krom has right, but is a little confusing implement the extension, so, we need only add at the end of the Swift controller (or class) that code that adds the "append" methods, nothing else.
Using the appendIfArray method, I could pass from this
[
{
"id_usuario" : 2
}
]
...to this
[
{
"id_usuario" : 2
},
{
"id_usuario" : 111
},
{
"id_usuario" : 112
},
{
"id_usuario" : 113
}
]
The complete code is below:
do{
try json2!["usuarios"][indice]["fotos"][0]["me_gusta"].appendIfArray(json: JSON( ["id_usuario": 111] ))
try json2!["usuarios"][indice]["fotos"][0]["me_gusta"].appendIfArray(json: JSON( ["id_usuario": 112] ))
try json2!["usuarios"][indice]["fotos"][0]["me_gusta"].appendIfArray(json: JSON( ["id_usuario": 113] ))
}catch {
print("Error")
}
The complete JSON structure can find in
http://jsoneditoronline.org/?id=56988c404dcd3c8b3065a583f9a41bba
I hope this can be useful

Related

Swiftui User Multiple Selection To Array of Object

I have the following response from API
"features": [
{
"name": "Safety",
"_id": "636a638959d10a2603b8d645",
"values": [
Array of String
]
},
{
"name": "Entertainment",
"_id": "636a64312bbe0cd292a1ffc6",
"values": [
Array of String
]
Which I decode it with :
struct Feature : Codable , Hashable{
var name : String = ""
var values : [Value] = []
}
struct Value : Codable, Hashable{
var value : String = ""
var unit : String = ""
}
And in the view is render it like :
var body: some View {
VStack{
HStack{
Text("Choose Your Features").font(Font.body.bold())
Spacer()
}.padding(.leading, 15)
ScrollView(.vertical, showsIndicators: false){
VStack{
ForEach(Array(features.enumerated()), id: \.offset) { featureIndex, feature in
HStack{
Text(feature.name).font(Font.body.bold())
Spacer()
}.padding(.bottom , 10)
ScrollView(.horizontal, showsIndicators: false){
HStack(spacing : 10){
ForEach(Array(feature.values.enumerated()), id: \.offset) { valueIndex, value in
FeatureCell(isSelected: $isSelected, value: value).onTapGesture{
// here
}
}
}
Divider().padding(10)
}
}.padding(15)
}
}
}
}
The user may select multiple item from each feature values list, Now Im really confused about how to store these selections in an array of features object again, I tried almost every thing like Array, Set and Dictionaries but could not reach any solution.
Update : This is the json object I should send back
{
"features": [
{
"Safety": [
"value1",
"value9",
"value3"
]
},
{
"Entertainment": [
"value7",
"value2",
"value8"
]
}
]
}
Any help or ideas will be much appreciated
You usually want to use a Set to store which items are selected. This set should be a State variable instantiated in the parent view. The onTapGesture closure will add or remove the value to the set. If the FeatureCell needs to know whether the value is selected, simply use the .contains method.
struct FeatureValueSelectionView: View {
// The feature whose values we are displaying
let feature: Feature
// Note: You may have to manually conform Value to the Hashable protocol
#State private var selectedValues = Set<Value>()
var body: some View {
ForEach(feature.values) { value in
FeatureCell(selected: selectedValues.contains(value), value: value)
.onTapGesture { selectedValues.toggle(value) }
}
}
}
For toggling a value in a set, I like to use this simple extension:
extension Set {
public mutating func toggle(_ element: Element) {
if self.contains(element) {
self.subtract([element])
} else {
self.insert(element)
}
}
}

How to use key and value from json response in tableview in iOS swift?

In tableview, each cell with key and value labels, i can able to pass static key value to tableview but now trying to get data from Json response to show in tableview.
here is my json response:
{
"d": {
"results": [
{
"__metadata": {
"id": "http://192.168.41.27:8009/sap/opu/odata/sap/Z_MM_PO_01_SRV/POItemSetSet('4500022401')",
"uri": "http://192.168.41.27:8009/sap/opu/odata/sap/Z_MM_PO_01_SRV/POItemSetSet('4500022401')",
"type": "Z_MM_PO_01_SRV.POItemSet"
},
"PoDocNo": "4500022401",
"Item": "00010",
"Material": "RMECC_MOB1",
"StorageLocation": "3001",
"MatGroup": "00107",
"Quantity": "2.000",
"OrderUnit": "KG",
"NetPrice": "1000.000",
"UnitofPrice": "1.000",
"ItemCat": "0",
"Requistor": ""
},
{
"__metadata": {
"id": "http://192.168.41.27:8009/sap/opu/odata/sap/Z_MM_PO_01_SRV/POItemSetSet('4500022401')",
"uri": "http://192.168.41.27:8009/sap/opu/odata/sap/Z_MM_PO_01_SRV/POItemSetSet('4500022401')",
"type": "Z_MM_PO_01_SRV.POItemSet"
},
"PoDocNo": "4500022401",
"Item": "00020",
"Material": "RMECC_MOB1",
"StorageLocation": "3001",
"MatGroup": "00107",
"Quantity": "2.000",
"OrderUnit": "KG",
"NetPrice": "1000.000",
"UnitofPrice": "1.000",
"ItemCat": "0",
"Requistor": ""
}
]
}
}
here i'm getting json response:
extension PoItemDetailsViewController {
func GetPoItemCount() {
if orderNo != nil {
// Call API
print("orderni::\(orderNo!)")
PoVendorListApiManager.sharedInstance.getPoListWithModel(orderString: orderNo!){ (json:JSON) in
// return json from API
if let categories = json["d"]["results"].dictionary {
print("catefory::\(self.categories)")
for (key, value) : (String, JSON) in categories {
self.dict[key] = value.object as AnyObject
}
print("dict:::\(self.dict)")
// for key in categories.keys {
// if let category =
categories[key]?.stringValue {
//
self.categories.updateValue(category, forKey: key)
// }
//
// }
}
print("catefory::\(self.categories)")
}
}
}
}//extension
here is my model:
import SwiftyJSON
struct poItems {
var key: String?
var value: String?
}
here is my static value i have passed to table view:
private var PoItems: [poItems]?
private var poVendorItemArray = [PoVendorModel]()
private func loadPoItems() -> [poItems] {
var tempItems = [poItems]()
let item1 = poItems.init(key: "Material#", value: "")
let item2 = poItems.init(key: "Quantity", value: "Bottles")
let item3 = poItems.init(key: "StorageLocation", value: "KP04")
let item4 = poItems.init(key: "PoDocNo", value: "KP Suppliers")
let item5 = poItems.init(key: "NetPrice", value: "1000")
return tempItems
}
how can i pass json reponse with key and value dynamically into tableview?
Any help much appreciates pls...
Please reread my answer in your earlier question (or read the JSON)
The value for results is an array
if let categories = json["d"]["results"].array {
print("category::\(self.categories)")
for category in categories {
for (key, value) in category {
print(key, value)
}
}
}
And – as suggested in many of your previous questions and in the comments – you are encouraged to drop SwiftyJSON and use Codable.

Cannot get data from a js array with Node js

I have a js object array like this.
[
{
name:"Japanilainen ravintola Koto",
rating:3.9,
photo:[
{
height:2160,
html_attributions:[
"Hannes Junnila"
],
photo_reference:"CoQBdwAAAMDlivT0nOnYg8jC1txZ3RbfBR59XvKN0WphDbRVUXaUTQclzzaIaXJ8-p7s3x_aG67AUsM_HLNML6pzGl3v_wV2D-eudH_3wy2cB1ROrRgGcGyf4lRuNpE3WwXYbYZu6EK8oEPiJ5B17Lybj-eVbYM2EgVVBgOrUJhsblY1mfxWEhAZ4oHCFakH-hgkbksfGa2uGhQe4aUeOrS2isAir01KUwQ7N3Ce2Q",
width:2269
}
]
},
{
name:"Kin Sushi Helsinki",
rating:4.2,
photo:[
{
height:2988,
html_attributions:[
"Stephan Winter"
],
photo_reference:"CoQBdwAAAN4iMumSbQjtRnJIH1AKRdbSfnI02WGh11r1xaVnZl1ohebKp6zpAS4mmJFqTagrIqUJ39kzulVI0sz2UzzfaVdsAFc5f80PnOCzSLqL5gnpsqv90dVJIqUWD3Bcc9TgYPPs3oGwyekkOsmjQ59o9yqdoF5GzrpaKkojhMNLxpfzEhBKpRkA2CzINpUzAAe3e90TGhQ_KbYCmtJYLfVGIu1kZkzQIAwE4A",
width:5312
}
]
}
]
I get this array above by doing this for each.
response.results.forEach((entry)=>{
var restaurantName = {
"name" : entry.name,
"rating" : entry.rating,
"photo_reference" : entry.photos
}
arr.push(restaurantName);
});
res.send(arr);
And I send the array to my browser so I can see it.
What I am trying to do is to get photo_reference from the entry.photos
I tried entry.photos[0].photo_reference and many more ways and in all of them I am getting a cannot read properly, and now I am not sure how to get that information out.
I edited some of the variable names to make it easier to simulate here, but just map the objects in the photo arrays to their references, and you'll get an array of photo references.
const data = [
{
name:"Japanilainen ravintola Koto",
rating:3.9,
photo:[
{
height:2160,
html_attributions:[
'Hannes Junnila'
],
photo_reference:"CoQBdwAAAMDlivT0nOnYg8jC1txZ3RbfBR59XvKN0WphDbRVUXaUTQclzzaIaXJ8-p7s3x_aG67AUsM_HLNML6pzGl3v_wV2D-eudH_3wy2cB1ROrRgGcGyf4lRuNpE3WwXYbYZu6EK8oEPiJ5B17Lybj-eVbYM2EgVVBgOrUJhsblY1mfxWEhAZ4oHCFakH-hgkbksfGa2uGhQe4aUeOrS2isAir01KUwQ7N3Ce2Q",
width:2269
}
]
},
{
name:"Kin Sushi Helsinki",
rating:4.2,
photo:[
{
height:2988,
html_attributions:[
'Stephan Winter'
],
photo_reference:"CoQBdwAAAN4iMumSbQjtRnJIH1AKRdbSfnI02WGh11r1xaVnZl1ohebKp6zpAS4mmJFqTagrIqUJ39kzulVI0sz2UzzfaVdsAFc5f80PnOCzSLqL5gnpsqv90dVJIqUWD3Bcc9TgYPPs3oGwyekkOsmjQ59o9yqdoF5GzrpaKkojhMNLxpfzEhBKpRkA2CzINpUzAAe3e90TGhQ_KbYCmtJYLfVGIu1kZkzQIAwE4A",
width:5312
}
]
}
]
const arr = []
data.forEach((entry)=>{
var restaurantName = {
"name" : entry.name,
"rating" : entry.rating,
"photo_reference" : entry.photo.map(x => x.photo_reference)
}
arr.push(restaurantName);
});
console.log(arr);
entry.photoes is not defined in your response.results object array.. did you mean to access it as entry.photo (inside your foreach function) ?

Filter a Parse query with an Array of [AnyObject] in Swift

I have an array of AnyObject objects in Swift (eventually, this array will be populated by querying a Parse database). Each object in the array has attributes of a publication, such as fullTitle, url, and journal. How can I filter the array to select all objects that match the search string for any value (e.g. where the fullTitle, url, or journal include "Forbes")?
Below is example code from a playground. First the sample array:
var publication1 = [
"fullTitle": "My first blog",
"url": "www.forbes.com/post1",
"journal": "Forbes
]
var publication2 = [
"fullTitle": "My second blog",
"url": "www.wsj.com/post1",
"journal": "Wall Street Journal"
]
var publications: [AnyObject] = [publication1, publication2]
Then, the filter function:
func filterContentForSearchText(searchText: String) {
let filteredPublications = publications.filter() {
if let fullTitle = ($0)["fullTitle"] as? String {
return fullTitle.rangeOfString(searchText) != nil
} else {
return false
}
}
}
Now, if I call the function with "first" as an argument, it should return the first object out of the array:
println(filterContentForSearchText("first"))
However, this command gives no result. How can I fix this? Also, how can I query all fields of the object for the searchText, not just the fullTitle field?
Thank you.
Here's a simple example that returns an array of matches in all fields:
func filterContentForSearchTextInAllFields(searchText: String) -> [String] {
var results = [String]()
for publication in publications {
for (key, value) in publication {
if (value as NSString).containsString(searchText) {
results.append(value)
}
}
}
return results
}
println(filterContentForSearchTextInAllFields("blog"))
This one only works on titles:
func filterContentForSearchText(searchText: String) -> [String] {
var results = [String]()
for publication in publications {
if let fullTitle = publication["fullTitle"] {
if (fullTitle as NSString).containsString(searchText) {
results.append(fullTitle)
}
}
}
return results
}
println(filterContentForSearchText("first"))
UPDATE
Here's a version for what you've asked in the comments:
func filterContentForSearchText(searchText: String) -> [[String:String]] {
var results = [[String:String]]()
for publication in publications {
if let fullTitle = publication["fullTitle"] as? String {
if (fullTitle as NSString).containsString(searchText) {
results.append(publication as! [String : String])
}
}
}
return results
}
println(filterContentForSearchText("first"))
Your "rows" are dictionaries: in the loop we assign each one to the "publication" variable, so we just take the one whose title matches the search terms then append it to an array of dictionaries.
Here is the route I went. Instead of an array of AnyObject I just let Swift infer the type
var publications = [publication1, publication2]
func searchPublications(seachText: String) -> [[String: String]] {
let filteredPublications = publications.filter { $0
for (_, value) in $0 {
if let found = value.rangeOfString(seachText, options: NSStringCompareOptions.CaseInsensitiveSearch, range: Range<String.Index>(start: value.startIndex, end: value.endIndex), locale: NSLocale.currentLocale()) {
return true
}
}
return false
}
return filteredPublications
}
Swift 3.0
This is worked for me.
I want filter data by it's status 0 or 1.
var arrRooms:[[String:AnyObject]] = [
[
"id": 30 as AnyObject,
"name": "Earth" as AnyObject,
"status": 0 as AnyObject,
"duration": 10 as AnyObject
],
[
"id": 27 as AnyObject,
"name": "Mars" as AnyObject,
"status": 1 as AnyObject,
"duration": 0 as AnyObject
]
]
let StatusPredicate = NSPredicate(format: "status = 1 ")
let arrFilter:[[String:AnyObject]] = (arrRooms as NSArray).filtered(using: StatusPredicate) as! [[String : AnyObject]]
print(arrFilter);
// output [["name": Mars, "status": 1, "id": 27, "duration": 0]]
it may be useful.thanks

Swift - NSDictionary multidimensional

currently i am working on a class which initializes an multidimensional array:
class Manager {
var data: Dictionary<String,NSDictionary>
init(data: Dictionary<String,NSDictionary>) {
func getApiData() {
getApiDataResource() { responseObject, error in
let resourceA = responseObject!
self.data["resources"] = resourceA
}
}
}
}
The responseObject which is returned asyncronously has this structure:
{
"data": [
{
id: 1
name: "Name1"
},
{
id: 2
name: "Name2"
}
],
"count": 2,
"success": true
}
The structure i want to get in my "data"-variable:
{
"resources": [
{
"resourceA":
{
"data": [
{
id: 1
name: "Name1"
},
{
id: 2
name: "Name2"
}
],
"count": 2,
"success": true
}
},
{
"resourceB": // and so on ...
}
]
}
But when saving my responseObject into my "data"-variable:
self.data["resources"] = resourceAData // this line fails
It prints:
Cannot assign to the result of this expression
Anybody could help me with this problem??
Thanks and Greetings!
I assume there is a function defined as follow:
func getApiDataResource(callback: (responseObject:NSDictionary?, error:NSError?) -> ()) {
// data retrieved from server at warp 8 here and other futuristic things
}
Step 1 (required)
I moved the function getApiData outside the init.
class Manager {
var data: Dictionary<String,NSDictionary>
init(data: Dictionary<String,NSDictionary>) {
getApiData()
}
func getApiData() {
getApiDataResource() { responseObject, error in
let resourceA = responseObject!
self.data["resources"] = resourceA
}
}
}
Now the compiler is complaining about this:
Use of self in method call getApiData before all store properties are initialized
and this
Return from initializer without initializing all stored properties
(As stated by you in a comment)
Fine. Let's fix it.
Step 2 (required)
class Manager {
var data: Dictionary<String,NSDictionary>
init(data: Dictionary<String,NSDictionary>) {
self.data = data
getApiData()
}
func getApiData() {
getApiDataResource() { responseObject, error in
let resourceA = responseObject!
self.data["resources"] = resourceA
}
}
}
Now it does compiles properly.
However I would adjust a couple of other things.
Step 3 (suggested)
Inside the trailing closure you are using the !. You should avoid this when possible. And you are not checking the error parameter that could be not nil.
You should use conditional unwrapping that is a safe alternative to the force unwrap (you did with !).
class Manager {
var data: Dictionary<String,NSDictionary>
init(data: Dictionary<String,NSDictionary>) {
self.data = data
getApiData()
}
func getApiData() {
getApiDataResource() { responseObject, error in
if let resourceA = responseObject where error == nil {
self.data["resources"] = resourceA
}
}
}
}
Now the code does not crash if responseObject from the closure is nil.
Step 4 (just a preference)
This is just a style preference.
Swift allows you to define your dictionary this way (as you did).
Dictionary<String,NSDictionary>
or this way:
[String:NSDictionary]
The 2 statement are equivalent. I just find more essential the second one. So...
class Manager {
var data: [String:NSDictionary]
init(data: [String:NSDictionary]) {
self.data = data
getApiData()
}
private func getApiData() {
getApiDataResource() { responseObject, error in
if let resourceA = responseObject where error == nil {
self.data["resources"] = resourceA
}
}
}
}
Let me know is this is what you need!
You have let data: Dictionary<String, Array<String>>, should be var data: Dictionary<String, Array<String>>

Resources