Decode JSON that has dynamic key - ios

I have response that looks like below JSON. The problem is I have dynamic key which is hashed. I am pretty lost in creating a Decodable struct for this response.
I have tried below code but it fails with data mismatch because of planName got introduced recently.
struct ProductDescriptionResponse {
let disclaimersHtml: String?
let additionalProperties: [String: ProductDescription]?
}
struct ProductDescription {
var disclaimersHtml: String?
var hasPlanDetailsV2: Bool?
let planDescription: String
let serviceDescriptions: [ServiceDescriptions]
}
struct ServiceDescriptions {
let name: String
let subTitle: String?
let icon: String?
let description: String?
let upgradeText: String?
let featureDisclaimer: String?
}
func productDescriptions() -> Observable<ProductDescriptionResponse> {
return APIClient.sharedInstance.rx.response(apiURL: APIURL.productDescription, requestType: .get, httpBody: nil, header: .auth).map({ (responseData) -> ProductDescriptionResponse in
var parsedData = try JSONSerialization.jsonObject(with: responseData) as? [String:Any]
// Remove disclaimersHtml key from responseData & hold it to pass
// in ProductDescriptionResponse constructor during return.
let disclaimersHtml = parsedData?.removeValue(forKey: "disclaimersHtml") as? String
// Product descriptions.
var productDescriptions: [String: ProductDescription]? = nil
if let parsedData = parsedData {
// Json data without disclaimersHtml.
let jsonData = try JSONSerialization.data(withJSONObject: parsedData, options: .prettyPrinted)
productDescriptions = try JSONDecoder().decode([String: ProductDescription].self, from: jsonData)
}
// ProductDescriptionResponse with disclaimersHtml & productDescriptions.
return ProductDescriptionResponse(disclaimersHtml: disclaimersHtml,
additionalProperties: productDescriptions)
})
}
JSON Response:
{
"disclaimersHtml": "",
"planName": "",
“abc456753234”: {
"planDescription": "",
"hasPlanDetailsV2": false,
"serviceDescriptions": [
{
"name": "",
"subTitle": "",
"icon": "",
"hasTile": "",
"tileTitle": "",
"description": "",
"featureDisclaimer": "",
"upgradeText": ""
},
{
"name": "",
"subTitle": "",
"icon": "",
"hasTile": "",
"tileTitle": "",
"description": "",
"featureDisclaimer": "",
"upgradeText": ""
}
]
},
“xyz123456789”: {
"planDescription": "",
"hasPlanDetailsV2": true,
"serviceDescriptions": [
{
"name": "",
"subTitle": "",
"icon": "",
"hasTile": "",
"tileTitle": "",
"description": "",
"featureDisclaimer": "",
"upgradeText": ""
}
]
}
}
If I do below, it works. But don't want to keep on hardcoding like this:
let _ = parsedData?.removeValue(forKey: "planName") as? String
Is there any better for this type of JSON to get working? I don't want to hardcode and keep stripping of values to get ProductDescriptionResponse because this field can get added in future.

I would solve this problem using CustomCodingKeys:
struct ProductDescriptionResponse: Decodable {
let disclaimersHtml: String?
let additionalProperties: [String: ProductDescription]?
var disclaimersHtml: String? = nil
var additionalProperties: [String: ProductDescription]? = nil
private struct CustomCodingKeys: CodingKey {
var stringValue: String
init?(stringValue: String) {
self.stringValue = stringValue
}
var intValue: Int?
init?(intValue: Int) {
return nil
}
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CustomCodingKeys.self)
self.additionalProperties = [String: ProductDescription]()
for key in container.allKeys {
do {
if let keyValue = CustomCodingKeys(stringValue: key.stringValue) {
if keyValue.stringValue == "disclaimersHtml" {
self.disclaimersHtml = try container.decodeIfPresent(String.self, forKey: keyValue)
}
self.additionalProperties?[keyValue.stringValue] = try container.decodeIfPresent(ProductDescription.self, forKey: keyValue)
}
} catch {
// Silently ignore the error
}
}
}
}
func productDescriptions() -> Observable<ProductDescriptionResponse> {
return APIClient.sharedInstance.rx.response(memberAPIURL: MemberAPIURL.productDescription, requestType: .get, httpBody: nil, header: .auth).map({ (response) -> ProductDescriptionResponse in
return try JSONDecoder().decode(ProductDescriptionResponse.self, from: response)
})
}

The way I solved is iterate through (key, value) of serialized JSON.
Check value is of type Dictionary<AnyHashable,Any> and decode only if that matches, else ignore.
func productDescriptions() -> Observable<ProductDescriptionResponse> {
return APIClient.sharedInstance.rx.response(memberAPIURL: MemberAPIURL.productDescription, requestType: .get, httpBody: nil, header: .auth).map({ (responseData) -> ProductDescriptionResponse in
var productDescriptionResponse = ProductDescriptionResponse(disclaimersHtml: nil, additionalProperties: nil)
var additionalParams: [String: ProductDescription] = [:]
do {
productDescriptionResponse = try JSONDecoder().decode(ProductDescriptionResponse.self, from: responseData)
if let jsonObject = try JSONSerialization.jsonObject(with: responseData, options: .mutableLeaves) as? [String : Any] {
for (key,value) in jsonObject {
if value is Dictionary<AnyHashable,Any> {
let jsonData = try JSONSerialization.data(withJSONObject: value, options: JSONSerialization.WritingOptions.prettyPrinted)
let productDescription = try JSONDecoder().decode(ProductDescription.self, from: jsonData)
additionalParams[key] = productDescription
}
}
productDescriptionResponse.additionalProperties = additionalParams
}
} catch {
// handle error
}
return productDescriptionResponse
})
}

Related

`keyNotFound` error when creating object from Gmail API Response with Swift on iOS

I'm using Alamofire to get emails from the Gmail API via the message IDs:
AF.request("https://www.googleapis.com/gmail/v1/users/me/messages/\(id)?format=full", headers: headers)
.responseJSON { [self] response in
do {
let json = try JSON(data: response.data!)
if let rawString = json.rawString() {
let email = try Email(rawString)
} else {
print("json.rawString is nil")
}
emailFetchGroup.leave()
}
catch {
print(error)
emailFetchGroup.leave()
}
}
And I have the following class, Email, that I'm trying to create from via the JSON response:
// This file was generated from JSON Schema using quicktype, do not modify it directly.
// To parse the JSON, add this file to your project and do:
//
// let email = try Email(json)
import Foundation
// MARK: - Email
class Email: Codable {
let sizeEstimate: Int
let historyID, threadID: String
let payload: Payload
let internalDate, snippet, id: String
let labelIDS: [String]
enum CodingKeys: String, CodingKey {
case sizeEstimate
case historyID = "historyId"
case threadID = "threadId"
case payload, internalDate, snippet, id
case labelIDS = "labelIds"
}
init(sizeEstimate: Int, historyID: String, threadID: String, payload: Payload, internalDate: String, snippet: String, id: String, labelIDS: [String]) {
self.sizeEstimate = sizeEstimate
self.historyID = historyID
self.threadID = threadID
self.payload = payload
self.internalDate = internalDate
self.snippet = snippet
self.id = id
self.labelIDS = labelIDS
}
}
// MARK: Email convenience initializers and mutators
extension Email {
convenience init(data: Data) throws {
let me = try newJSONDecoder().decode(Email.self, from: data)
self.init(sizeEstimate: me.sizeEstimate, historyID: me.historyID, threadID: me.threadID, payload: me.payload, internalDate: me.internalDate, snippet: me.snippet, id: me.id, labelIDS: me.labelIDS)
}
convenience init(_ json: String, using encoding: String.Encoding = .utf8) throws {
guard let data = json.data(using: encoding) else {
throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
}
try self.init(data: data)
}
convenience init(fromURL url: URL) throws {
try self.init(data: try Data(contentsOf: url))
}
func with(
sizeEstimate: Int? = nil,
historyID: String? = nil,
threadID: String? = nil,
payload: Payload? = nil,
internalDate: String? = nil,
snippet: String? = nil,
id: String? = nil,
labelIDS: [String]? = nil
) -> Email {
return Email(
sizeEstimate: sizeEstimate ?? self.sizeEstimate,
historyID: historyID ?? self.historyID,
threadID: threadID ?? self.threadID,
payload: payload ?? self.payload,
internalDate: internalDate ?? self.internalDate,
snippet: snippet ?? self.snippet,
id: id ?? self.id,
labelIDS: labelIDS ?? self.labelIDS
)
}
func jsonData() throws -> Data {
return try newJSONEncoder().encode(self)
}
func jsonString(encoding: String.Encoding = .utf8) throws -> String? {
return String(data: try self.jsonData(), encoding: encoding)
}
}
// MARK: - Payload
class Payload: Codable {
let mimeType: String
let headers: [Header]
let body: Body
let partID, filename: String
enum CodingKeys: String, CodingKey {
case mimeType, headers, body
case partID = "partId"
case filename
}
init(mimeType: String, headers: [Header], body: Body, partID: String, filename: String) {
self.mimeType = mimeType
self.headers = headers
self.body = body
self.partID = partID
self.filename = filename
}
}
// MARK: Payload convenience initializers and mutators
extension Payload {
convenience init(data: Data) throws {
let me = try newJSONDecoder().decode(Payload.self, from: data)
self.init(mimeType: me.mimeType, headers: me.headers, body: me.body, partID: me.partID, filename: me.filename)
}
convenience init(_ json: String, using encoding: String.Encoding = .utf8) throws {
guard let data = json.data(using: encoding) else {
throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
}
try self.init(data: data)
}
convenience init(fromURL url: URL) throws {
try self.init(data: try Data(contentsOf: url))
}
func with(
mimeType: String? = nil,
headers: [Header]? = nil,
body: Body? = nil,
partID: String? = nil,
filename: String? = nil
) -> Payload {
return Payload(
mimeType: mimeType ?? self.mimeType,
headers: headers ?? self.headers,
body: body ?? self.body,
partID: partID ?? self.partID,
filename: filename ?? self.filename
)
}
func jsonData() throws -> Data {
return try newJSONEncoder().encode(self)
}
func jsonString(encoding: String.Encoding = .utf8) throws -> String? {
return String(data: try self.jsonData(), encoding: encoding)
}
}
// MARK: - Body
class Body: Codable {
let size: Int
let attachmentID: String
enum CodingKeys: String, CodingKey {
case size
case attachmentID = "attachmentId"
}
init(size: Int, attachmentID: String) {
self.size = size
self.attachmentID = attachmentID
}
}
// MARK: Body convenience initializers and mutators
extension Body {
convenience init(data: Data) throws {
let me = try newJSONDecoder().decode(Body.self, from: data)
self.init(size: me.size, attachmentID: me.attachmentID)
}
convenience init(_ json: String, using encoding: String.Encoding = .utf8) throws {
guard let data = json.data(using: encoding) else {
throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
}
try self.init(data: data)
}
convenience init(fromURL url: URL) throws {
try self.init(data: try Data(contentsOf: url))
}
func with(
size: Int? = nil,
attachmentID: String? = nil
) -> Body {
return Body(
size: size ?? self.size,
attachmentID: attachmentID ?? self.attachmentID
)
}
func jsonData() throws -> Data {
return try newJSONEncoder().encode(self)
}
func jsonString(encoding: String.Encoding = .utf8) throws -> String? {
return String(data: try self.jsonData(), encoding: encoding)
}
}
// MARK: - Header
class Header: Codable {
let name, value: String
init(name: String, value: String) {
self.name = name
self.value = value
}
}
// MARK: Header convenience initializers and mutators
extension Header {
convenience init(data: Data) throws {
let me = try newJSONDecoder().decode(Header.self, from: data)
self.init(name: me.name, value: me.value)
}
convenience init(_ json: String, using encoding: String.Encoding = .utf8) throws {
guard let data = json.data(using: encoding) else {
throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
}
try self.init(data: data)
}
convenience init(fromURL url: URL) throws {
try self.init(data: try Data(contentsOf: url))
}
func with(
name: String? = nil,
value: String? = nil
) -> Header {
return Header(
name: name ?? self.name,
value: value ?? self.value
)
}
func jsonData() throws -> Data {
return try newJSONEncoder().encode(self)
}
func jsonString(encoding: String.Encoding = .utf8) throws -> String? {
return String(data: try self.jsonData(), encoding: encoding)
}
}
// MARK: - Helper functions for creating encoders and decoders
func newJSONDecoder() -> JSONDecoder {
let decoder = JSONDecoder()
if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) {
decoder.dateDecodingStrategy = .iso8601
}
return decoder
}
func newJSONEncoder() -> JSONEncoder {
let encoder = JSONEncoder()
if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) {
encoder.dateEncodingStrategy = .iso8601
}
return encoder
}
This almost works perfectly; except for the attachmentID parameter - when I try to create an email, I get this error:
keyNotFound(CodingKeys(stringValue: "attachmentId", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "payload", intValue: nil), CodingKeys(stringValue: "body", intValue: nil)], debugDescription: "No value associated with key CodingKeys(stringValue: \"attachmentId\", intValue: nil) (\"attachmentId\").", underlyingError: nil))
Kind of at my whit's end on this; so any help appreciated - what do I need to do to make sure that this property will get assigned?
EDIT I forgot to include the JSON response; which is below:
{
"snippet" : "",
"id" : "1758550e1d57a61e",
"internalDate" : "1604259323000",
"sizeEstimate" : 1811162,
"threadId" : "1758549a183c08f0",
"payload" : {
"partId" : "",
"mimeType" : "video\/mp4",
"filename" : "nicholasarner#gmail.com-2020_11_01_11_35_23-WDYT?.mp4",
"body" : {
"size" : 1322930,
"attachmentId" : "ANGjdJ_nEZvNaV972a1H9osO7Ze3WH-F5hlf8cSEQjgM9NmI8XzsKsfhAF_zV7addIHsIEgm8nmlPGID8pICD5ew8399hocuXwvfGVx_Pl3Z7f1jwgmrm1_UD6k1daGkaXFFy7kbfiiRRidy42IoKT9r3FoS4tb7mVmv7ctrQE9KvCjV2Op3MCkzvrjM494iG06yJtQhM5Zt697BG-kythaCjacFJ5cTh4c-qdCN60JIUL3sR95AWnoEvSBMVr_i6iPKIP67gpddw27MkMmqICA8jkJXXSGhGaZek2hJu886ik_3VCvqlQ4c2uypWVYNOfWMPvjVuNmlW-_MH41cSo_mqd2DaxBVkXut70bu24y2-aY50ljhVZRqhV6CSoUlbBiPEe_VxToATBy_vFLF8TZRlOGg5Jq0kleymZvRgg"
},
"headers" : [
{
"name" : "Return-Path",
"value" : "<nicholasarner#gmail.com>"
},
{
"name" : "Received",
"value" : "from iPhone ([2601:645:4200:3950:441:1411:7e85:db6d]) by smtp.gmail.com with ESMTPSA id u124sm12113464pfc.21.2020.11.01.11.35.24 for <nicholasarner#gmail.com> (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128\/128); Sun, 01 Nov 2020 11:37:51 -0800 (PST)"
},
{
"name" : "Date",
"value" : "Sun, 1 Nov 2020 11:35:23 -0800"
},
{
"name" : "From",
"value" : "nicholasarner#gmail.com"
},
{
"name" : "To",
"value" : "Nick Arner <nicholasarner#gmail.com>"
},
{
"name" : "Message-ID",
"value" : "<d5ff6514-1c55-4d98-a4d3-43a776d7b05d#iPhone>"
},
{
"name" : "In-Reply-To",
"value" : "<CAD1H43XCrKQD3omFV2ggf_e2kLm_v4234p2oHvvKGd-bJ4PZeQ#mail.gmail.com>"
},
{
"name" : "Subject",
"value" : "Re: tett"
},
{
"name" : "MIME-Version",
"value" : "1.0"
},
{
"name" : "Content-Type",
"value" : "video\/mp4"
},
{
"name" : "Content-Transfer-Encoding",
"value" : "base64"
},
{
"name" : "Content-Disposition",
"value" : "attachment; filename=\"nicholasarner#gmail.com-2020_11_01_11_35_23-WDYT?.mp4\""
}
]
},
"historyId" : "11441245",
"labelIds" : [
"IMPORTANT",
"SENT",
"INBOX"
]
}

How to parse part of json data into table

How to parse following json which I want to parse only few part.
```
{
"head": {
"StatusValue": 200,
"StatusText": "Success"
},
"body": {
"Data": [
{
"payer_type_id": 1,
"payer_type": "Self Pay"
},
{
"payer_type_id": 2,
"payer_type": "Corporate"
},
{
"payer_type_id": 6,
"payer_type": "Insurance"
}
],
"RecordCount": 3,
"TotalRecords": null
}
}
How to parse only data inside Data key.
Expected result should be in following format
Date = [["payer_type_id": 1,"payer_type": "Self Pay"],["payer_type_id": 2,"payer_type": "Corporate"],["payer_type_id": 6,"payer_type": "Insurance"]]
You can use Codable protocol for your parsing .
Create Your Model
struct APIRootModel : Codable {
let head : HeaderModel
let body : BodyModel
}
struct HeaderModel :Codable{
let StatusValue : Int
let StatusText : String
}
struct BodyModel : Codable{
let Data : [DataModel]
}
struct DataModel : Codable{
let payer_type_id : Int
let payer_type : String
}
Decode your json using JSONDecoder()
let decoder = JSONDecoder()
do {
let rootModel = try decoder.decode(APIRootModel.self, from: jsonData)
print(rootModel.body.data)
} catch {
print(error)
}
Use [DataModel] for your tableview datasource.
Try this:
let jsonString = "your json string here"
let dictObject = getDictionaryFromJsonString(dictString: jsonString)
let bodyDict = dictObject["body"]
let dataArray = bodyDict["Data"]
func getDictionaryFromJsonString(dictString:String)->
[String: Any] {
do {
return try JSONSerialization.jsonObject(with:
dictString.data(using: String.Encoding.utf8,
allowLossyConversion: true)!, options:
JSONSerialization.ReadingOptions.allowFragments) as!
Dictionary
} catch {
return [:]
}
}

Not able to parse api response

I have an api response that looks like so…I get the response from the api properly..
{
"status": "success",
"data": {
"meta": {
"url": "htt..://www.abc.com",
"title": “ASD - Log In or Sign Up",
"description": "Create an account or log in….”,
"display_url": "htt..://www.abc.com/",
"video_url": "",
"image": "htt..://www.asd.com/images/asds_325x325.png",
"img_wxh": "325x325"
}
}
}
The model class with which I parse this data is given like so..
struct MetaData: Codable {
let status: String?
let data: DataClass?
}
struct DataClass: Codable {
let meta: Meta
}
struct Meta: Codable {
let url: String
let title, description: String
let displayURL: String
let videoURL: String
let image: String
let imgWxh: String
enum CodingKeys: String, CodingKey {
case url = "url"
case title = "title"
case description = "description"
case displayURL = "display_url"
case videoURL = "video_url"
case image = "image"
case imgWxh = "img_wxh"
}
}
The api call that is being made is gives as below...
WebServiceClient.shared.getMeta(withParameters: parameters) { [weak self] (isSuccess, result) in
guard let `self` = self else { return }
if isSuccess, result != nil {
if let jsonData = try? JSONSerialization.data(withJSONObject: result as Any, options: []) {
do {
let metaData = try JSONDecoder().decode(MetaData.self, from: jsonData)
self.metaDataImageView.sd_setImage(with: URL(string: metaData.data?.meta.image ?? ""), completed: nil)
self.urlLabel.text = metaData.data?.meta.url
self.titleLabel.text = metaData.data?.meta.title
self.urlDescriptionLabel.text = metaData.data?.meta.description
} catch {
print("error \(error)")
}
}
}
But I get all data as nil...what could be the reason..?
I get nothing in metaData...
Here is the code I tried to parse your data
struct MetaData: Codable {
let status: String?
let data: DataClass?
}
struct DataClass: Codable {
let meta: Meta
}
struct Meta: Codable {
let url: String
let title, description: String
let displayURL: String
let videoURL: String
let image: String
let imgWxh: String
enum CodingKeys: String, CodingKey {
case url = "url"
case title = "title"
case description = "description"
case displayURL = "display_url"
case videoURL = "video_url"
case image = "image"
case imgWxh = "img_wxh"
}
}
let jsonString = """
{
"status": "success",
"data": {
"meta": {
"url": "htt..://www.abc.com",
"title": "ASD - Log In or Sign Up ",
"description": "Create an account or log in….",
"display_url": "htt..://www.abc.com/",
"video_url": "",
"image": "htt..://www.asd.com/images/asds_325x325.png",
"img_wxh": "325x325"
}
}
}
"""
let jsonData = jsonString.data(using: .utf8)
do {
let parsedData = try JSONDecoder().decode(MetaData.self, from: jsonData!)
print(parsedData)
} catch {
print(error.localizedDescription)
}
And it works.
Also your json have some issue so make sure you validate your json format.
you can use jsonlint.com for validating json.

Objects inside Array inside Object Swift

Can somebody help with parsing this kind of JSON object?
{
"array":[
{
"title":"",
"desc":""
},
{
"title":"",
"desc":""
},
{
"title":"",
"desc":""
}
]
}
My code doesnt work
let task = self.session.dataTask(with: url) {
data, response, error in
if let data = data,
let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
for case let announcment in json!["array"]{
guard let title = announcment["title"] as? String,
let description = announcment["desc"] as? String,
else{ return }
}
task.resume()
Thank in advance for any help!
Pretty-printing your JSON makes it easier to work through:
{
"array":[
{
"title":"",
"desc":""
},
{
"title":"",
"desc":""
},
{
"title":"",
"desc":""
}
]
}
You need to get the array first. An array of dictionaries is of type [[String: Any]].
let task = self.session.dataTask(with: url) {
data, response, error in
if let data = data,
let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
guard let announcements = json["array"] as? [[String: Any]]
else { return }
announcements.forEach { announcement in
guard let title = announcement["title"] as? String,
let description = announcement["desc"] as? String
else { return }
// Do something with the result
}
}
}
task.resume()
You can structure your data and make it Codable:
struct Root: Codable {
let array: [Announcement]
}
struct Announcement: Codable {
let title: String
let desc: String
}
let data = Data("""
{"array":[{"title":"","desc":""},{"title":"","desc":""},{"title":"","desc":""}]}
""".utf8)
do {
let announcements = try JSONDecoder().decode(Root.self, from: data).array
for announcement in announcements {
print(announcement)
}
} catch {
print(error)
}
This will print
Announcement(title: "", desc: "")
Announcement(title: "", desc: "")
Announcement(title: "", desc: "")

Values are not updating in my text label from api calling

I have one api calling, and I am passing one parameter value to that api. And I am doing append to one model data and from there I am trying to display in my label. But when I do api calling itself and try to print the label name , Its showing crash index out of range
func showprofileapi () {
let headers = [
"cache-control": "no-cache",
"postman-token": "4c933910-0da0-b199-257b-28fb0b5a89ec"
]
let jsonObj:Dictionary<String, Any> = [
"customerID" : "5"
]
if (!JSONSerialization.isValidJSONObject(jsonObj)) {
print("is not a valid json object")
return
}
if let postData = try? JSONSerialization.data(withJSONObject: jsonObj, options: JSONSerialization.WritingOptions.prettyPrinted) {
let request = NSMutableURLRequest(url: NSURL(string: "http://MyProfile.php")! as URL,
cachePolicy: .useProtocolCachePolicy,timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
if (error != nil) {
///print(error)
} else {
DispatchQueue.main.async(execute: {
if let json = (try? JSONSerialization.jsonObject(with: data!, options: [])) as? Dictionary<String,AnyObject>
{
let status = json["status"] as? Int;
if(status == 1)
{
print("SUCCESS....")
if (json["myprofile"] as? NSDictionary) != nil
{
print("SUCCESS ......22....")
print(json)
DispatchQueue.main.async(execute: {
print("INSIDE CATEGORIES")
self.Profileddatas.append(MyProfiledData(json:json as NSDictionary))
print("Product Name : ", self.Profileddatas[0].custName)
})
}
}
}
})
}
})
dataTask.resume()
}
}
My above code is my api calling, And when I try to print the value in my console its crashing :
// print("Product Name : ", self.Profileddatas[0].custName)
My json output after api calling is :
{
"status": 1,
"message": "My Profile Details are.",
"myprofile": {
"CustomerName": "ram",
"CustomerEmail": "ram#gmail.com",
"CustomerMobile": "",
"CustomerAddress": "",
"CustomerUsername": "",
"CustomerPassword": " "
}
}
My append data model class is :
class MyProfiledData
{
var custName : String?
var custEmail : String?
var custMobile : String?
var custAddress : String?
var custUsername : String?
var custPassword : String?
init(json:NSDictionary)
{
self.custName = json["CustomerName"] as? String
self.custEmail = json["CustomerEmail"] as? String
self.custMobile = json["CustomerMobile"] as? String
self.custAddress = json["CustomerAddress"] as? String
self.custUsername = json["CustomerUsername"] as? String
self.custPassword = json["CustomerPassword"] as? String
}
}
Please help me out.
Thanks
change if (json["myprofile"] as? NSDictionary) != nil
to if let json = json["myprofile"] as? NSDictionary because your 'json' in the context of initializing MyProfiledData went wrong
You're accessing the JSON Data by it's wrong keys in Your MyProfileData Class. You have either pass the ["myprofile"] dict in the init(json) call by
if let myProfile = json["myprofile"] as? NSDictionary {
DispatchQueue.main.async(execute: {
self.Profiledatas.append(MyProfileData(json:myProfile))
})
}
or access it by their right Keys:
class MyProfiledData {
var custName : String?
var custEmail : String?
var custMobile : String?
var custAddress : String?
var custUsername : String?
var custPassword : String?
init(json:NSDictionary) {
self.custName = json["myprofile"]["CustomerName"] as? String
self.custEmail = json["myprofile"]["CustomerEmail"] as? String
self.custMobile = json["myprofile"]["CustomerMobile"] as? String
self.custAddress = json["myprofile"]["CustomerAddress"] as? String
self.custUsername = json["myprofile"]["CustomerUsername"] as? String
self.custPassword = json["myprofile"]["CustomerPassword"] as? String
}
}
In your init function it structure is not ok, it will be work if you send only my profile node of your json
{
"CustomerName": "ram",
"CustomerEmail": "ram#gmail.com",
"CustomerMobile": "",
"CustomerAddress": "",
"CustomerUsername": "",
"CustomerPassword": " "
}
use
self.Profileddatas.append(MyProfiledData(json:Json["myprofile"] as NSDictionary))
if (json["myprofile"] as? NSDictionary) != nil
{
print("SUCCESS ......22....")
print(json)
DispatchQueue.main.async(execute: {
print("INSIDE CATEGORIES")
self.Profileddatas.append(MyProfiledData(json:json["myprofile"] as! NSDictionary))
print("Product Name : ", self.Profileddatas[0].custName)
self.getvalue ()
})
}

Resources