Search in Mapped JSON - ios

I need to implement search within this JSON, I've tried to do it but it's giving me error. Below is my code and Modal Class which I've mapped.
After trying every possible way, I still cannot resolve this error.
My code for search:
self.company = self.companyDetails.filter{ _ in self.companyDetails.company_name.range(of: searchKey) }
Showing error:
Value of type '[companiesDetail]' has no member 'company_name'
Alamofire.request("http://34.210.142.70/isdental/api/v2.0/home/companies", method: .get, parameters: nil, encoding: URLEncoding.default, headers: params).responseObject { (response:DataResponse<ContactRealm>) in
let ContactsRes = response.result.value
self.companyDetails = ContactsRes?.companies as! [companiesDetail]
self.company = ContactsRes?.companies as! [companiesDetail]
}
Below is My JSON :
{
"error": false,
"message": "Companies fetched succesfully",
"companies": [
{
"company_id": 1,
"company_name": "3M Espe India",
"company_image": "https://project-isdental-cammy92.c9users.io/api/images/v2.0/companies/3m_espe.png",
"company_website": "http://solutions.3mindia.co.in/wps/portal/3M/en_IN/3M-ESPE-APAC/",
"company_email": "",
"company_description": "",
"company_categories": "General Equipment / Preventives & Oral Care / General & Restorative",
"company_contacts": [
{
"contact_id": 1,
"contact_name": "Zonal Office",
"contact_image": "https://project-isdental-cammy92.c9users.io/api/images/v2.0/contacts/company_office.png",
"contact_phone": "+91 8022231414",
"contact_location": "Bangalore",
"contact_favourite": false,
"contact_email": "3mespe.in#mmm.com",
"contact_website": "",
"contact_type": 1
},
{
"contact_id": 367,
"contact_name": "3A Dental Company",
"contact_image": "https://project-isdental-cammy92.c9users.io/api/images/v2.0/contacts/dealer.png",
"contact_phone": "+91 9811082743",
"contact_location": "Delhi",
"contact_favourite": false,
"contact_email": "3adental#sify.com",
"contact_website": "",
"contact_type": 4
},
{
"contact_id": 368,
"contact_name": "Avco Consultancy",
"contact_image": "https://project-isdental-cammy92.c9users.io/api/images/v2.0/contacts/dealer.png",
"contact_phone": "+91 9811155330",
"contact_location": "Delhi",
"contact_favourite": false,
"contact_email": "avcoindia#gmail.com",
"contact_website": "",
"contact_type": 4
},
{
"contact_id": 369,
"contact_name": "Biotech Agencies",
"contact_image": "https://project-isdental-cammy92.c9users.io/api/images/v2.0/contacts/dealer.png",
"contact_phone": "+91 9811132274",
"contact_location": "Delhi",
"contact_favourite": false,
"contact_email": "BIOTECHAGENCIES#GMAIL.COM",
"contact_website": "",
"contact_type": 4
},
{
"contact_id": 370,
"contact_name": "Lexical",
"contact_image": "https://project-isdental-cammy92.c9users.io/api/images/v2.0/contacts/dealer.png",
"contact_phone": "+91 9810015540",
"contact_location": "Delhi",
"contact_favourite": false,
"contact_email": "lexicaldental#gmail.com",
"contact_website": "",
"contact_type": 4
},
{
"contact_id": 371,
"contact_name": "Oramco",
"contact_image": "https://project-isdental-cammy92.c9users.io/api/images/v2.0/contacts/dealer.png",
"contact_phone": "+91 9810263014",
"contact_location": "Delhi",
"contact_favourite": false,
"contact_email": "oramco#yahoo.com",
"contact_website": "",
"contact_type": 4
},
{
"contact_id": 372,
"contact_name": "Unicorn Denmart",
"contact_image": "https://project-isdental-cammy92.c9users.io/api/images/v2.0/contacts/dealer.png",
"contact_phone": "+91 9810986086",
"contact_location": "Delhi",
"contact_favourite": false,
"contact_email": "achla#unicorndenmart.com",
"contact_website": "",
"contact_type": 4
}]}]}
Below is My Mapped Class :
import Foundation
import RealmSwift
import ObjectMapper
struct ContactRealm: Mappable {
init?(map: Map) {
}
var companies:Array<companiesDetail>?
mutating func mapping(map: Map) {
self.companies <- map["companies"]
self.filters <- map["filters"]
}
}
struct companiesDetail: Mappable {
init?(map: Map) {
}
var company_id : Int?
var company_name: String?
var company_image : String?
var company_website : String?
var company_email: String?
var company_description : String?
var company_categories : String?
var company_contacts:Array<companycontacts>?
mutating func mapping(map: Map) {
self.company_id <- map["company_id"]
self.company_name <- map["company_name"]
self.company_image <- map["company_image"]
self.company_website <- map["company_website"]
self.company_email <- map["company_email"]
self.company_description <- map["company_description"]
self.company_categories <- map["company_categories"]
self.company_contacts <- map["company_contacts"]
}
}
struct companycontacts: Mappable {
init?(map: Map) {
}
var contact_id : Int?
var contact_name : String?
var contact_image : String?
var contact_phone : String?
var contact_location : String?
var contact_favourite : String?
var contact_email : String?
var contact_website : String?
var contact_type : Int?
mutating func mapping(map: Map) {
self.contact_id <- map["contact_id"]
self.contact_name <- map["contact_name"]
self.contact_image <- map["contact_image"]
self.contact_phone <- map["contact_phone"]
self.contact_location <- map["contact_location"]
self.contact_favourite <- map["contact_favourite"]
self.contact_email <- map["contact_email"]
self.contact_website <- map["contact_website"]
self.contact_type <- map["contact_type"]
}
}

Related

getting only one item from decoding json response iOS

I've a response from MapBox API. I want to store each Feature object of features array in a array then want to display from that array to table view.
{
type: "FeatureCollection",
query: [
"u"
],
features: [{
id: "country.19678805456372290",
type: "Feature",
place_type: [
"country"
],
relevance: 1,
properties: {
wikidata: "Q30",
short_code: "us"
},
text: "United States",
place_name: "United States",
matching_text: "US",
matching_place_name: "US",
bbox: [
-179.9,
18.8163608007951,
-66.8847646185949,
71.4202919997506
],
center: [
-97.9222112121185,
39.3812661305678
],
geometry: {
type: "Point",
coordinates: [
-97.9222112121185,
39.3812661305678
]
}
},
{
id: "country.12405201072814600",
type: "Feature",
place_type: [
"country"
],
relevance: 1,
properties: {
wikidata: "Q145",
short_code: "gb"
},
text: "United Kingdom",
place_name: "United Kingdom",
bbox: [
-8.74974065661991,
49.802416901086,
1.86276379960989,
60.9093517989553
],
center: [
-2.36966957036279,
54.2379333607472
],
geometry: {
type: "Point",
coordinates: [
-2.36966957036279,
54.2379333607472
]
}
},
{
id: "country.11702916565595680",
type: "Feature",
place_type: [
"country"
],
relevance: 1,
properties: {
wikidata: "Q878",
short_code: "ae"
},
text: "United Arab Emirates",
place_name: "United Arab Emirates",
bbox: [
51.4160146192147,
22.6282410017159,
56.4814183948386,
26.094609499407
],
center: [
54.2561723713588,
23.8520599823879
],
geometry: {
type: "Point",
coordinates: [
54.2561723713588,
23.8520599823879
]
}
},
{
id: "country.11871993712476590",
type: "Feature",
place_type: [
"country"
],
relevance: 1,
properties: {
wikidata: "Q212",
short_code: "ua"
},
text: "Ukraine",
place_name: "Ukraine",
bbox: [
22.1375690033684,
44.3152913001972,
40.2255909904191,
52.3793529890401
],
center: [
31.3202829593814,
49.3227937844972
],
geometry: {
type: "Point",
coordinates: [
31.3202829593814,
49.3227937844972
]
}
},
{
id: "country.9140805109496660",
type: "Feature",
place_type: [
"country"
],
relevance: 1,
properties: {
wikidata: "Q77",
short_code: "uy"
},
text: "Uruguay",
place_name: "Uruguay",
matching_text: "URY",
matching_place_name: "URY",
bbox: [
-58.4891219951353,
-35.0552819973662,
-53.1014000735687,
-30.0855740544354
],
center: [
-56.012396238658,
-32.7996455126793
],
geometry: {
type: "Point",
coordinates: [
-56.012396238658,
-32.7996455126793
]
}
}
],
attribution: "NOTICE: © 2021 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained. POI(s) provided by Foursquare."
}
So, I create a model like this -
struct Response: Codable {
var features: [Feature]
}
struct Feature: Codable {
var id: String!
var type: String?
var matching_place_name: String?
var place_name: String?
var geometry: Geometry
var center: [Double]
var properties: Properties
}
struct Geometry: Codable {
var type: String?
var coordinates: [Double]
}
struct Properties: Codable {
var address: String?
}
And Write this code -
var suggestedPlacenames: NSMutableArray = []
func doShowSuggestion(usersQuery: String) {
let urlString = "\(mapbox_api)\(usersQuery).json?access_token=\(mapbox_access_token)"
let url = URL(string: urlString)
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
guard let data = data, error == nil else {
print("Error in URLSeesion")
return
}
if let result = try? JSONDecoder().decode(Response.self, from: data) {
self.suggestedPlacenames.add(result)
print(self.suggestedPlacenames.count)
} else {}
But by this I always get 1 length from self.suggestedPlacenames whatever the length of the response in features. How can I get each features object separately in self.suggestedPlacenames?
In your code :
self.suggestedPlacenames.add(result)
You add only one element to your array.
You must append the an array.
// declare as an array of features
var suggestedPlacenames = [Feature]()
self.suggestedPlacenames.append(contentsOf: result.features)
or
self.suggestedPlacenames += result.features
You need to delcare
var allFeatures = [Feature]()
do {
let result = try JSONDecoder().decode(Response.self, from: data)
self.allFeatures = result.features
print(self.allFeatures.count)
}
catch {
print(error)
}
Then

How do i parse custom JSON Data

Here i provide the code worked sample as per the guideline given below and seems to get null values.
Here is my complete JSON Data,
some: {
"success": true,
"data":
[
{
"15-10-2020": [
{
"id": 100,
"details": {
"_id": 1,
"_title": "My Title"
},
"created_at": "2020-10-15"
},
{
"snf_id": 101,
"details": {
"_id": 1,
"_title": "My Title"
},
"created_at": "2020-10-15"
},
{
"snf_id": 102,
"details": {
"_id": 1,
"_title": "My Title"
},
"created_at": "2020-10-15"
}
],
"30-09-2020": [
{
"snf_id": 301,
"details": {
"_id": 8,
"_title": "My Title"
},
"created_at": "2020-09-30"
}
]
}
],
"message": "Successfully Retrieved"
}
struct Response : Codable {
var success : Bool?
var data : [Data]?
var message : String?
}
struct Data: Codable {
var snf_id: Int?
var details: Details?
var created_at: String?
}
// MARK: - Details
struct Details: Codable {
var _id: Int?
var _title: String?
}
let Response = try JSONDecoder().decode(Response.self, from: data)
Returns null value for data,
▿ Response
▿ success : Optional
- some : true
▿ data : Optional<Array>
▿ some : 1 element
▿ 0 : Data
- snf_id : nil
- details : nil
- created_at : nil
▿ message : Optional
- some : "Successfully Retrieved"
There is no myData key in your json , your json top structure is an array that contains elements where every element value is an array like [[String: [Root]]]
struct Root: Codable {
let id: Int?
let details: Details
let createdAt: String
let snfID: Int?
enum CodingKeys: String, CodingKey {
case id, details
case createdAt = "created_at"
case snfID = "snf_id"
}
}
// MARK: - Details
struct Details: Codable {
let id: Int
let title: String
enum CodingKeys: String, CodingKey {
case id = "_id"
case title = "_title"
}
}
And to decode
let res = try JSONDecoder().decode([[String: [Root]]].self,from:data)
some: {
"success": true,
"data":
[
{
"15-10-2020": [
{
"id": 100,
"details": {
"_id": 1,
"_title": "My Title"
},
"created_at": "2020-10-15"
},
{
"snf_id": 101,
"details": {
"_id": 1,
"_title": "My Title"
},
"created_at": "2020-10-15"
},
{
"snf_id": 102,
"details": {
"_id": 1,
"_title": "My Title"
},
"created_at": "2020-10-15"
}
],
"30-09-2020": [
{
"snf_id": 301,
"details": {
"_id": 8,
"_title": "My Title"
},
"created_at": "2020-09-30"
}
]
}
],
"message": "Successfully Retrieved"
}
struct Response : Codable {
var success : Bool?
**var data : [[String:[Data]]]?**
var message : String?
}
struct Data: Codable {
var snf_id: Int?
var details: Details?
var created_at: String?
}
// MARK: - Details
struct Details: Codable {
var _id: Int?
var _title: String?
}
let Response = try JSONDecoder().decode(Response.self, from: data)

Merge Two Array of Struct in Swift

I am receiving response from server like below. Here, review and rating are in separate object and the booking_id is same.
{
"status": "Success",
"records": [
{
"user_name": "123user",
"review": "Ggg",
"booking_id": "Booking_23749",
"review_id": "review_38405",
"status": "active"
},
{
"_id": "5e0c43ea5bd0377f4cfdfa19",
"user_name": "123user",
"rating": 5,
"booking_id": "Booking_23749"
}
]
}
Then I have created a Modal struct to store the data coming from server.
struct ReviewRecord: Codable, Equatable {
static func == (lhs: ReviewRecord, rhs: ReviewRecord) -> Bool {
return lhs.bookingID == rhs.bookingID
}
let userName, review, bookingID, reviewID: String?
let status, id: String?
let rating: Int?
enum CodingKeys: String, CodingKey {
case userName = "user_name"
case review
case bookingID = "booking_id"
case reviewID = "review_id"
case status
case id = "_id"
case rating
}
}
and I am using it as,
var reviewsData = [ReviewRecord]() // appending all data received in reviewsData
Question : How to merge the two objects to create one final object. So basically, I want it to make it like this:
[
"review": "Ggg",
"review_id": "review_38405",
"status": "active"
"_id": "5e0c43ea5bd0377f4cfdfa19",
"user_name": "123user",
"rating": 5,
"booking_id": "Booking_23749"
]
UPDATE
More detail on what actually I am trying to achieve:
if there are four records in json like this :
{
"user_name": "123user",
"review": "Ggg",
"booking_id": "Booking1",
"review_id": "review_38405",
"status": "active"
},
{
"_id": "5e0c43ea5bd0377f4cfdfa19",
"user_name": "123user",
"rating": 5,
"booking_id": "Booking1"
},
{
"user_name": "123user",
"review": "Ggg",
"booking_id": "Booking2",
"review_id": "review_38405",
"status": "active"
},
{
"_id": "5e0c43ea5bd0377f4cfdfa19",
"user_name": "123user",
"rating": 5,
"booking_id": "Booking2"
}
I need to merge booking1 and booking2 like this:
{
"user_name": "123user",
"review": "Ggg",
"booking_id": "Booking1",
"review_id": "review_38405",
"status": "active"
"_id": "5e0c43ea5bd0377f4cfdfa19",
"rating": 5,
},
{
"user_name": "123user",
"review": "Ggg",
"booking_id": "Booking2",
"review_id": "review_38405",
"status": "active"
"_id": "5e0c43ea5bd0377f4cfdfa19",
"rating": 5,
}
I hope its much clear now.
The JSON
Given this JSON
let data = """
{
"status": "Success",
"records": [
{
"user_name": "123user",
"review": "Ggg",
"booking_id": "Booking_23749",
"review_id": "review_38405",
"status": "active"
},
{
"_id": "5e0c43ea5bd0377f4cfdfa19",
"user_name": "123user",
"rating": 5,
"booking_id": "Booking_23749"
}
]
}
""".data(using: .utf8)!
And given the associated Codable struct
We need to add the merged(with: method to the Record struct
struct Response: Decodable {
let status: String
let records: [Record]
struct Record: Decodable {
let userName: String?
let review: String?
let bookingID: String
let reviewID: String?
let status: String?
let id: String?
let rating: Int?
enum CodingKeys: String, CodingKey {
case userName = "user_name"
case review
case bookingID = "booking_id"
case reviewID = "review_id"
case status
case id = "_id"
case rating
}
func merged(with record: Record) -> Record? {
guard bookingID == record.bookingID else { return nil }
return Record(userName: userName ?? record.userName,
review: review ?? record.review,
bookingID: bookingID,
reviewID: reviewID ?? record.reviewID,
status: status ?? record.status,
id: id ?? record.id,
rating: rating ?? record.rating
)
}
}
}
Decoding and merging
Now we can decode and merge the Record(s) having the same recordID
do {
let response = try JSONDecoder().decode(Response.self, from: data)
let mergedRecords = response
.records
.reduce(into: [String: Response.Record]()) { (result, record) in
guard let existingRecord = result[record.bookingID] else {
result[record.bookingID] = record
return
}
let merged = existingRecord.merged(with: record)
result[record.bookingID] = merged
}
.values
print(mergedRecords)
} catch {
print(error)
}
Result
[
Response.Record(
userName: Optional("123user"),
review: Optional("Ggg"),
bookingID: "Booking_23749",
reviewID: Optional("review_38405"),
status: Optional("active"),
id: Optional("5e0c43ea5bd0377f4cfdfa19"),
rating: Optional(5)
)
]
Consideratoins
This code will work for any number of elements into the records field of your input JSON.
UPDATE
I tested my code with your new input JSON
let data = """
{
"status": "Success",
"records": [
{
"user_name": "123user",
"review": "Ggg",
"booking_id": "Booking1",
"review_id": "review_38405",
"status": "active"
},
{
"_id": "5e0c43ea5bd0377f4cfdfa19",
"user_name": "123user",
"rating": 5,
"booking_id": "Booking1"
},
{
"user_name": "123user",
"review": "Ggg",
"booking_id": "Booking2",
"review_id": "review_38405",
"status": "active"
},
{
"_id": "5e0c43ea5bd0377f4cfdfa19",
"user_name": "123user",
"rating": 5,
"booking_id": "Booking2"
}
]
}
""".data(using: .utf8)!
And I got the expected result
[
Response.Record(userName: Optional("123user"),
review: Optional("Ggg"),
bookingID: "Booking1",
reviewID: Optional("review_38405"),
status: Optional("active"),
id: Optional("5e0c43ea5bd0377f4cfdfa19"),
rating: Optional(5)),
Response.Record(userName: Optional("123user"),
review: Optional("Ggg"),
bookingID: "Booking2",
reviewID: Optional("review_38405"),
status: Optional("active"),
id: Optional("5e0c43ea5bd0377f4cfdfa19"),
rating: Optional(5))
]
So please double check you are following exactly my instructions ;)
I think that a good approach for this will be create a merge function in your ReviewRecord model and then a dict of [String:ReviewRecord] where key is booking_id something like this
struct ReviewRecord: Codable, Equatable {
//All previous logic
func merge(_ anotherRecord: ReviewRecord) -> ReviewRecord {
let userName = self.userName ?? anotherRecord.userName
let review = self.review ?? anotherRecord.review
let reviewID = self.reviewID ?? anotherRecord.reviewID
let status = self.status ?? anotherRecord.status
let id = self.id ?? anotherRecord.id
let rating = self.rating ?? anotherRecord.rating
return ReviewRecord(userName: userName, review: review, bookingID: self.bookingID, reviewID: reviewID, status: status, id: id, rating: rating)
}
}
then where your are decoding
you need to make a cycle over your json dict objects and create one by one adding it to a dict
func getRecordsFromRequestData(data:Data?) -> [ReviewRecord] {
if let dataNew = data, let responseString = String(data: dataNew, encoding: .utf8) {
print("----- Records -----")
print(responseString)
print("----------")
do {
let jsonObject = try JSONSerialization.jsonObject(with: dataNew, options: .mutableContainers) as! AnyObject
if let recordsArray = jsonObject["records"] as? [AnyObject] {
var reviewsData = [String:ReviewRecord]()
for dictObj in recordsArray {
let dictData = try JSONSerialization.data(withJSONObject: dictObj, options: .fragmentsAllowed)
do {
var reviewRecord = try JSONDecoder().decode(ReviewRecord.self, from: dictData)
if reviewsData[reviewRecord.bookingID] != nil {
let finalRecord = reviewRecord.merge(reviewsData[reviewRecord.bookingID]!)
reviewsData[reviewRecord.bookingID] = finalRecord
} else {
reviewsData[reviewRecord.bookingID] = reviewRecord
}
}
catch {
}
}
let finalValue = reviewsData.map({$0.value})
debugPrint(finalValue)
return finalValue
}
}
catch {
}
}
return []
}
Output with first example json provided by question
[CodableQuestion.ReviewRecord(userName: Optional("123user"), review: Optional("Ggg"), reviewID: Optional("review_38405"), bookingID: "Booking_23749", status: Optional("active"), id: Optional("5e0c43ea5bd0377f4cfdfa19"), rating: Optional(5))]
Output with second example json provided by updated question
[CodableQuestion.ReviewRecord(userName: Optional("123user"), review: Optional("Ggg"), reviewID: Optional("review_38405"), bookingID: "Booking1", status: Optional("active"), id: Optional("5e0c43ea5bd0377f4cfdfa19"), rating: Optional(5)),
CodableQuestion.ReviewRecord(userName: Optional("123user"), review: Optional("Ggg"), reviewID: Optional("review_38405"), bookingID: "Booking2", status: Optional("active"), id: Optional("5e0c43ea5bd0377f4cfdfa19"), rating: Optional(5))]

how to parse a JSON with Array of Dictionaries iOS swift

I am having a JSON array which looks like this:
func fetchProfessionalData() {
guard let url = URL(string:"urlString") else { return }
let parameters = ["Address":""] as [String : Any]
Alamofire.request(url, method: .post, parameters:parameters,encoding: JSONEncoding.default, headers: nil).responseJSON {
response in
switch response.result {
case .success:
let jsonData = response.result.value as! NSArray
print("response:\(jsonData)")
}
self.listTableView.reloadData()
break
case .failure(let error):
print(error)
}
}
}
this is the output I'm getting when I print it:
response: [
{
"userId": 2,
"userName": "jhonsmith",
"password": "1234",
"userTypeId": 3,
"firstName": "jhon",
"lastName": "smith",
"dob": "0004-03-04T00:00:00",
"phoneNumber": "40556677",
"mobile": "324",
"email": "jhon",
"profilePic": "avatar3.jpg",
"profileImage": null,
"isDeleted": false,
"company": "",
"experience": "2 years",
"about": "I am expertised in beauty care",
"addressId": 2,
"addressLine1": "7 Freymuth Rd",
"addressLine2": "",
"city": "St.Louis",
"state": "MO",
"country": "USA",
"zipCode": "63367",
"serviceProviderId": 0,
"serviceId": 0,
"subServiceId": 0,
"relevantExp": null,
"costPerHour": 0,
"spbRow": null,
"lstServiceProviders": [
{
"serviceId": 3,
"serviceName": "BeautyCare",
"serviceDescription": null,
"serviceLogo": null,
"serviceIsDeleted": false,
"serviceIdFK": 0,
"subServiceId": 5,
"subServiceName": "HairCare",
"subServiceDescription": null,
"subServiceLogo": null,
"subServiceIsDeleted": false,
"costPerHour": 500,
"serviceProviderId": 2,
"providerServiceId": 1
},
{
"serviceId": 4,
"serviceName": "Carpentry",
"serviceDescription": null,
"serviceLogo": null,
"serviceIsDeleted": false,
"serviceIdFK": 0,
"subServiceId": 6,
"subServiceName": "All Carpentry",
"subServiceDescription": null,
"subServiceLogo": null,
"subServiceIsDeleted": false,
"costPerHour": 400,
"serviceProviderId": 2,
"providerServiceId": 1002
}
],
"rating": 3,
"price": 0,
"searchLocationId": 0
},
{
"userId": 4,
"userName": "User",
"password": "new",
"userTypeId": 3,
"firstName": "Emma",
"lastName": "Williams",
"dob": "1998-06-23T00:00:00",
"phoneNumber": "7787787887",
"mobile": "9879789990",
"email": "user#testmail.com",
"profilePic": "avatar4.jpg",
"profileImage": null,
"isDeleted": false,
"company": "",
"experience": "2 years",
"about": "Test",
"addressId": 4,
"addressLine1": "Big river dr",
"addressLine2": "",
"city": "St.Louis",
"state": "MO",
"country": "USA",
"zipCode": "63367",
"serviceProviderId": 0,
"serviceId": 0,
"subServiceId": 0,
"relevantExp": null,
"costPerHour": 0,
"spbRow": null,
"lstServiceProviders": [
{
"serviceId": 1,
"serviceName": "Cleaning",
"serviceDescription": null,
"serviceLogo": null,
"serviceIsDeleted": false,
"serviceIdFK": 0,
"subServiceId": 1,
"subServiceName": "Dusting",
"subServiceDescription": null,
"subServiceLogo": null,
"subServiceIsDeleted": false,
"costPerHour": 2,
"serviceProviderId": 4,
"providerServiceId": 3
}
],
"rating": 0,
"price": 0,
"searchLocationId": 0
},
{
"userId": 5,
"userName": "RobertThomas",
"password": "rb",
"userTypeId": 3,
"firstName": "Robert",
"lastName": "Thomas",
"dob": "1999-01-04T00:00:00",
"phoneNumber": "889955643",
"mobile": "1234567890",
"email": "rb1234#testmail.com",
"profilePic": "th.jpg",
"profileImage": null,
"isDeleted": false,
"company": "",
"experience": "1 Year",
"about": "Robert Thomas",
"addressId": 5,
"addressLine1": "Little Piney Dr",
"addressLine2": "",
"city": "St.Louis",
"state": "MO",
"country": "USA",
"zipCode": "63367",
"serviceProviderId": 0,
"serviceId": 0,
"subServiceId": 0,
"relevantExp": null,
"costPerHour": 0,
"spbRow": null,
"lstServiceProviders": [
{
"serviceId": 2,
"serviceName": "ChildCare",
"serviceDescription": null,
"serviceLogo": null,
"serviceIsDeleted": false,
"serviceIdFK": 0,
"subServiceId": 3,
"subServiceName": "Baby Sitting",
"subServiceDescription": null,
"subServiceLogo": null,
"subServiceIsDeleted": false,
"costPerHour": 7,
"serviceProviderId": 5,
"providerServiceId": 4
}
],
"rating": 0,
"price": 0,
"searchLocationId": 0
}
]
Now I am having a tableViewCell where I have to show "userName", "profilePic","rating","email" and "serviceName" under "lstServiceProviders".So far I am able to show name,image,email,rating but "lstServiceProviders" is another array of dictionaries. I want to show all the services provided by that serviceProvider in cell.
lets say in json 1st dict the "userName":"jhonsmith" is having "lstServicePrpviders" with an array of two dictionaries with "serviceName": "BeautyCare" in 1st Dict and "serviceName":"Carpentry" in 2nd Dict. I want to show both BeautyCare and Carpentry in one cell. how to do this.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let listCell = tableView.dequeueReusableCell(withIdentifier: "listCell", for: indexPath) as! ListTableViewCell
let string = "imageBaseUrl\(models![indexPath.row].profilePic!)"
let escapedAddress = string.addingPercentEncoding(
withAllowedCharacters: CharacterSet.urlQueryAllowed)
listCell.listCellImage.image = UIImage(url: URL(string: escapedAddress!))
listCell.listCellNamesLabel.text = models![indexPath.row].userName!
let rating = models![indexPath.row].rating!
listCell.listCellRating.text = "(\(rating)/5 & 5 Comments)"
listCell.listCellStarRating.text = ratingArray[indexPath.row]
for i in 0..< models![indexPath.row].lstServiceProviders!.count {
listCell.listCellServicesLbl.text =
models![indexPath.row].lstServiceProviders[i].serviceName
}
return listCell
}
[Swift 4] You can use models with Codable to easily manage your tableviewcell.
See the Code below and run in a playground, you will understand that i have created model objects which is easy to loop and manage:
var json = """
[
{
"userId": 2,
"userName": "jhonsmith",
"password": "1234",
"userTypeId": 3,
"firstName": "jhon",
"lastName": "smith",
"dob": "0004-03-04T00:00:00",
"phoneNumber": "40556677",
"mobile": "324",
"email": "jhon",
"profilePic": "avatar3.jpg",
"profileImage": null,
"isDeleted": false,
"company": "",
"experience": "2 years",
"about": "I am expertised in beauty care",
"addressId": 2,
"addressLine1": "7 Freymuth Rd",
"addressLine2": "",
"city": "St.Louis",
"state": "MO",
"country": "USA",
"zipCode": "63367",
"serviceProviderId": 0,
"serviceId": 0,
"subServiceId": 0,
"relevantExp": null,
"costPerHour": 0,
"spbRow": null,
"lstServiceProviders": [
{
"serviceId": 3,
"serviceName": "BeautyCare",
"serviceDescription": null,
"serviceLogo": null,
"serviceIsDeleted": false,
"serviceIdFK": 0,
"subServiceId": 5,
"subServiceName": "HairCare",
"subServiceDescription": null,
"subServiceLogo": null,
"subServiceIsDeleted": false,
"costPerHour": 500,
"serviceProviderId": 2,
"providerServiceId": 1
},
{
"serviceId": 4,
"serviceName": "Carpentry",
"serviceDescription": null,
"serviceLogo": null,
"serviceIsDeleted": false,
"serviceIdFK": 0,
"subServiceId": 6,
"subServiceName": "All Carpentry",
"subServiceDescription": null,
"subServiceLogo": null,
"subServiceIsDeleted": false,
"costPerHour": 400,
"serviceProviderId": 2,
"providerServiceId": 1002
}
],
"rating": 3,
"price": 0,
"searchLocationId": 0
},
{
"userId": 4,
"userName": "User",
"password": "new",
"userTypeId": 3,
"firstName": "Emma",
"lastName": "Williams",
"dob": "1998-06-23T00:00:00",
"phoneNumber": "7787787887",
"mobile": "9879789990",
"email": "user#testmail.com",
"profilePic": "avatar4.jpg",
"profileImage": null,
"isDeleted": false,
"company": "",
"experience": "2 years",
"about": "Test",
"addressId": 4,
"addressLine1": "Big river dr",
"addressLine2": "",
"city": "St.Louis",
"state": "MO",
"country": "USA",
"zipCode": "63367",
"serviceProviderId": 0,
"serviceId": 0,
"subServiceId": 0,
"relevantExp": null,
"costPerHour": 0,
"spbRow": null,
"lstServiceProviders": [
{
"serviceId": 1,
"serviceName": "Cleaning",
"serviceDescription": null,
"serviceLogo": null,
"serviceIsDeleted": false,
"serviceIdFK": 0,
"subServiceId": 1,
"subServiceName": "Dusting",
"subServiceDescription": null,
"subServiceLogo": null,
"subServiceIsDeleted": false,
"costPerHour": 2,
"serviceProviderId": 4,
"providerServiceId": 3
}
],
"rating": 0,
"price": 0,
"searchLocationId": 0
},
{
"userId": 5,
"userName": "RobertThomas",
"password": "rb",
"userTypeId": 3,
"firstName": "Robert",
"lastName": "Thomas",
"dob": "1999-01-04T00:00:00",
"phoneNumber": "889955643",
"mobile": "1234567890",
"email": "rb1234#testmail.com",
"profilePic": "th.jpg",
"profileImage": null,
"isDeleted": false,
"company": "",
"experience": "1 Year",
"about": "Robert Thomas",
"addressId": 5,
"addressLine1": "Little Piney Dr",
"addressLine2": "",
"city": "St.Louis",
"state": "MO",
"country": "USA",
"zipCode": "63367",
"serviceProviderId": 0,
"serviceId": 0,
"subServiceId": 0,
"relevantExp": null,
"costPerHour": 0,
"spbRow": null,
"lstServiceProviders": [
{
"serviceId": 2,
"serviceName": "ChildCare",
"serviceDescription": null,
"serviceLogo": null,
"serviceIsDeleted": false,
"serviceIdFK": 0,
"subServiceId": 3,
"subServiceName": "Baby Sitting",
"subServiceDescription": null,
"subServiceLogo": null,
"subServiceIsDeleted": false,
"costPerHour": 7,
"serviceProviderId": 5,
"providerServiceId": 4
}
],
"rating": 0,
"price": 0,
"searchLocationId": 0
}
]
""".data(using: .utf8)
struct LstServiceProviders : Codable {
let serviceId : Int?
let serviceName : String?
let serviceDescription : String?
let serviceLogo : String?
let serviceIsDeleted : Bool?
let serviceIdFK : Int?
let subServiceId : Int?
let subServiceName : String?
let subServiceDescription : String?
let subServiceLogo : String?
let subServiceIsDeleted : Bool?
let costPerHour : Int?
let serviceProviderId : Int?
let providerServiceId : Int?
enum CodingKeys: String, CodingKey {
case serviceId = "serviceId"
case serviceName = "serviceName"
case serviceDescription = "serviceDescription"
case serviceLogo = "serviceLogo"
case serviceIsDeleted = "serviceIsDeleted"
case serviceIdFK = "serviceIdFK"
case subServiceId = "subServiceId"
case subServiceName = "subServiceName"
case subServiceDescription = "subServiceDescription"
case subServiceLogo = "subServiceLogo"
case subServiceIsDeleted = "subServiceIsDeleted"
case costPerHour = "costPerHour"
case serviceProviderId = "serviceProviderId"
case providerServiceId = "providerServiceId"
}
}
struct RootModel : Codable {
let userId : Int?
let userName : String?
let password : String?
let userTypeId : Int?
let firstName : String?
let lastName : String?
let dob : String?
let phoneNumber : String?
let mobile : String?
let email : String?
let profilePic : String?
let profileImage : String?
let isDeleted : Bool?
let company : String?
let experience : String?
let about : String?
let addressId : Int?
let addressLine1 : String?
let addressLine2 : String?
let city : String?
let state : String?
let country : String?
let zipCode : String?
let serviceProviderId : Int?
let serviceId : Int?
let subServiceId : Int?
let relevantExp : String?
let costPerHour : Int?
let spbRow : String?
let lstServiceProviders : [LstServiceProviders]?
let rating : Int?
let price : Int?
let searchLocationId : Int?
enum CodingKeys: String, CodingKey {
case userId = "userId"
case userName = "userName"
case password = "password"
case userTypeId = "userTypeId"
case firstName = "firstName"
case lastName = "lastName"
case dob = "dob"
case phoneNumber = "phoneNumber"
case mobile = "mobile"
case email = "email"
case profilePic = "profilePic"
case profileImage = "profileImage"
case isDeleted = "isDeleted"
case company = "company"
case experience = "experience"
case about = "about"
case addressId = "addressId"
case addressLine1 = "addressLine1"
case addressLine2 = "addressLine2"
case city = "city"
case state = "state"
case country = "country"
case zipCode = "zipCode"
case serviceProviderId = "serviceProviderId"
case serviceId = "serviceId"
case subServiceId = "subServiceId"
case relevantExp = "relevantExp"
case costPerHour = "costPerHour"
case spbRow = "spbRow"
case lstServiceProviders = "lstServiceProviders"
case rating = "rating"
case price = "price"
case searchLocationId = "searchLocationId"
}
}
let Models = try! JSONDecoder().decode([RootModel].self, from: json!)
print(Models.count)
for item in Models {
print(item.lstServiceProviders?.count)
}
[Edit 1] If the response is Data, use the below:
URLSession.shared.dataTask(with: gitUrl) { (data, response
, error) in
guard let data = data else { return }
do {
let decoder = JSONDecoder()
let models = try decoder.decode([RootModel].self, from: data)
} catch let err {
print("Err", err)
}
}.resume()
If the response is Json object like your output, use the below:
func fetchProfessionalData() {
guard let url = URL(string:"urlString") else { return }
let parameters = ["Address":""] as [String : Any]
Alamofire.request(url, method: .post, parameters:parameters,encoding: JSONEncoding.default, headers: nil).responseJSON {
response in
switch response.result {
case .success:
// let jsonData = response.result.value as! NSArray
let jsonData = try JSONSerialization.data(withJSONObject: response.result, options: .prettyPrinted)
models = try JSONDecoder().decode([RootModel].self, from: jsonData)
print("response:\(jsonData)")
}
// self.listTableView.reloadData()
break
case .failure(let error):
print(error)
}
}
}
In your viewController, Declare varibale
var models: [RootModel]? {
didSet {
self.listTableView.reloadData()
}
}
In your tableview delegate method
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return models.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Update your cell using models
// cell.text = models[indexPath.row].userName
}
[Edit 2] Add all string and then show the value.
var stringArray:[String] = []
for i in 0..< models![indexPath.row].lstServiceProviders!.count {
stringArray.append( models![indexPath.row].lstServiceProviders[i].serviceName)
}
listCell.listCellServicesLbl.text = stringArray.joined(separator: ", ")

Swift 4 - SwiftyJson compare array and merge found values

I have a JSON object which contains a list of names and values. I want to compare to it another array [String] and if the value is found in one of the JSON object value merge that value to a new object.
I have tried using merge(with) in a for loop however, it seems to be merge just one value.
> example:
>
> json_cat =
>
> {
> name: "aaa",
> surname: "aaa-1",
> grade: "aaa-2"
> },
> {
> name: "bbb",
> surname: "bbb-1",
> grade: "bbb-2"
> },
> {
> name: "ccc",
> surname: "ccc-1",
> grade: "ccc-2"
> }
>
//
> let arraytest:[String] = ["aaa", "ccc", "ddd"]
>
// array json_cat compare arraytest
> result = {
> name: "aaa",
> surname: "aaa-1",
> grade: "aaa-2"
> },
> {
> name: "ccc",
> surname: "ccc-1",
> grade: "ccc-2"
> }
let json_cat: JSON = "json from url"
let arraytest:[String] = ["aaa", "ccc", "ddd"]
var json_cat_array = JSON()
json_cat.forEach({ (index, json_p) in
if arraytest.contains(json_p["name"].string!) {
//print("\(index) - \(json_p)")
try! json_cat_array.merge(with: json_p)
}
})
You could implement your loop like this:
json_cat.forEach({ (index, json_p) in
if arraytest.contains(json_p["name"].string!) {
//print("\(index) - \(json_p)")
json_cat_array[json_p["name"].string!] = json_p
}
})
The merge function is really for merging data. Like in this example:
let original: JSON = [
"first_name": "John",
"age": 20,
"skills": ["Coding", "Reading"],
"address": [
"street": "Front St",
"zip": "12345",
]
]
let update: JSON = [
"last_name": "Doe",
"age": 21,
"skills": ["Writing"],
"address": [
"zip": "12342",
"city": "New York City"
]
]
let updated = original.merge(with: update)
// [
// "first_name": "John",
// "last_name": "Doe",
// "age": 21,
// "skills": ["Coding", "Reading", "Writing"],
// "address": [
// "street": "Front St",
// "zip": "12342",
// "city": "New York City"
// ]
// ]
This code uses Swift 4 foundation JSON parser. Swift 4 has got wonder parser by default.
import Foundation
let jsonString = """
[{
"surname": "Roxxy",
"grade": "neaou"
},
{
"name": "Puffi",
"surname": "Chips",
"grade": "meaou"
},
{
"name": "Taffy",
"surname": "Baby",
"grade": "mew-mew"
}]
"""
struct JsonCat: Decodable {
let name: String?
let surname: String
let grade: String
}
struct Cat {
let name: String
let surname: String
let grade: String
}
guard let jsonData = jsonString.data(using: .utf8), let jsonCats = try? JSONDecoder().decode([JsonCat].self, from: jsonData) else {
fatalError()
}
var cats: [Cat] = []
jsonCats.forEach { jsonCat in
guard let name = jsonCat.name else {
return
}
let cat = Cat(name: name, surname: jsonCat.surname, grade: jsonCat.grade)
cats.append(cat)
}
print(cats)

Resources