-2

I am getting JSON data by using Codable method. Here, In my JSON response most of the values receiving as a String but sometime it received Int. on that time I am getting Decoding Error like below

TypeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), CodingKeys(stringValue: "status", intValue: nil)], debugDescription: "Expected to decode String but found a number instead.", underlyingError: nil))

Codable

// MARK: - Welcome
struct Welcome: Codable {
    let status: Bool
    let data: DataClass
}

// MARK: - DataClass
struct DataClass: Codable {
    let memberID, groupID, memberName, dataDescription: String
    let duedate, team, member: String
    let membergroup: JSONNull?
    let teams, category, junction, grouptype: String
    let typegroup, groupMethod, memberCD, checklist: String
    let refID, startDate, createdBy, createdDate: String
    let startedBy: JSONNull?
    let startedDate: String
    let submittedBy, submittedDate, completedBy: JSONNull?
    let completedDate, extendDate: String
    let editedBy: JSONNull?
    let editedDate: String
    let status: Int
    let autotask, isdelete, timestamp, assignedMember: String
    let teamName, gemID, gemName, ticketName: String
    let ticketTypeName, ableToDelete, assignedForMe, priorityFlag: String
    let taskTypeFlag: String
    let comments, notification, reminder: [JSONAny]
    let acceptOrDecline: String
    let availableStatus: [AvailableStatus]
    let editedUserName: String

    enum CodingKeys: String, CodingKey {
        case memberID = "member_id"
        case groupID = "group_id"
        case memberName = "member_name"
        case dataDescription = "description"
        case duedate, team, member, membergroup, teams, category, junction, grouptype, typegroup
        case groupMethod = "group_method"
        case memberCD = "member_cd"
        case checklist
        case refID = "ref_id"
        case startDate = "start_date"
        case createdBy = "created_by"
        case createdDate = "created_date"
        case startedBy = "started_by"
        case startedDate = "started_date"
        case submittedBy = "submitted_by"
        case submittedDate = "submitted_date"
        case completedBy = "completed_by"
        case completedDate = "completed_date"
        case extendDate = "extend_date"
        case editedBy = "edited_by"
        case editedDate = "edited_date"
        case status, autotask, isdelete, timestamp
        case assignedMember = "assigned_member"
        case teamName = "team_name"
        case gemID = "gem_id"
        case gemName = "gem_name"
        case ticketName = "ticket_name"
        case ticketTypeName = "ticket_type_name"
        case ableToDelete = "able_to_delete"
        case assignedForMe = "assigned_for_me"
        case priorityFlag = "priority_flag"
        case taskTypeFlag = "task_type_flag"
        case comments, notification, reminder
        case acceptOrDecline = "accept_or_decline"
        case availableStatus = "available_status"
        case editedUserName = "edited_user_name"
    }
}

// MARK: - AvailableStatus
struct AvailableStatus: Codable {
    let id: Int
    let name, displayName, icon: String

    enum CodingKeys: String, CodingKey {
        case id, name
        case displayName = "display_name"
        case icon
    }
}
myapp store
  • 173
  • 11
  • It is hard to tell. check your JSON response, one of these String keys you declared are not strings in the JSON – Teja Nandamuri Sep 19 '19 at 18:11
  • @Teja Nandamuri my problem is codable with key that is sometimes an `String` and some times a `Int`. But from server we gave all String. How to handle this? is there anything mistake I did into the codable structure? – myapp store Sep 19 '19 at 18:13
  • But the posted json works, can't you show an example of when it goes wrong? – Joakim Danielson Sep 19 '19 at 18:30
  • @ Joakim Danielson `typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), CodingKeys(stringValue: "team", intValue: nil)], debugDescription: "Expected to decode String but found an array instead.", underlyingError: nil))` Still I am getting issues keep on. – myapp store Sep 19 '19 at 18:33
  • I mean to post the json and not the error but if you are getting errors on all possible kind of values then it is probably the server that is broken. "But from server we gave all String", does this mean that it is your own server application? – Joakim Danielson Sep 19 '19 at 18:35
  • @Joakim Danielson No, This kind of issues most of the developers facing. I seen this example https://stackoverflow.com/questions/47935705/using-codable-with-key-that-is-sometimes-an-int-and-other-times-a-string – myapp store Sep 19 '19 at 18:37
  • Then why don't you implement the answer posted in that question. – Joakim Danielson Sep 19 '19 at 18:38
  • I need to confirm my codable structure properly implemented because I am very new for this. Also, I seen that example I really cant able to understand. I would like to know what exactly wrong and how to fix that? @Joakim Danielson – myapp store Sep 19 '19 at 18:39
  • @vadian can you help me on this? – myapp store Sep 19 '19 at 18:56
  • I don't think I can give a clearer answer than in the link and besides since you are having issues with different values it is not obvious how much it is that needs to be fixed. Also, you didn't answer my question if this was your own server application? – Joakim Danielson Sep 19 '19 at 19:01
  • @ Joakim Danielson Yes, its my own server application. initially it will be local and we are going to move Cloud instance – myapp store Sep 19 '19 at 19:04
  • Then I suggest you fix the server application so that it delivers consistent data, otherwise you will be facing a lot of extra work and possible bugs. – Joakim Danielson Sep 19 '19 at 19:05
  • @ Joakim Danielson You mean I need to move from local to Cloud Instance. So, That it will be solve. Am I right? – myapp store Sep 19 '19 at 19:06
  • Don't add space after @ when writing a user name, it mean I don't get a notification that you have posted something addressed to me. So it should be @username. As for the question, it has nothing to do with iCloud it is about the content of the json data you send from your server is sometimes incorrect and that you need to send the right type of data all the time. – Joakim Danielson Sep 19 '19 at 19:49
  • @vadian can you help me on this? – myapp store Sep 20 '19 at 03:11

1 Answers1

1

you can do this:

// MARK: - Welcome
class Welcome: Codable {
    let status: Bool
    let data: DataClass
}

// MARK: - DataClass
class DataClass: Codable {
    let memberID, groupID, memberName, dataDescription: String
    let duedate, team, member: String
    let membergroup: JSONNull?
    let teams, category, junction, grouptype: String
    let typegroup, groupMethod, memberCD, checklist: String
    let refID, startDate, createdBy, createdDate: String
    let startedBy: JSONNull?
    let startedDate: String
    let submittedBy, submittedDate, completedBy: JSONNull?
    let completedDate, extendDate: String
    let editedBy: JSONNull?
    let editedDate: String
    let status: Int
    let autotask, isdelete, timestamp, assignedMember: String
    let teamName, gemID, gemName, ticketName: String
    let ticketTypeName, ableToDelete, assignedForMe, priorityFlag: String
    let taskTypeFlag: String
    let comments, notification, reminder: [JSONAny]
    let acceptOrDecline: String
    let availableStatus: [AvailableStatus]
    let editedUserName: String

    enum CodingKeys: String, CodingKey {
        case memberID = "member_id"
        case groupID = "group_id"
        case memberName = "member_name"
        case dataDescription = "description"
        case duedate, team, member, membergroup, teams, category, junction, grouptype, typegroup
        case groupMethod = "group_method"
        case memberCD = "member_cd"
        case checklist
        case refID = "ref_id"
        case startDate = "start_date"
        case createdBy = "created_by"
        case createdDate = "created_date"
        case startedBy = "started_by"
        case startedDate = "started_date"
        case submittedBy = "submitted_by"
        case submittedDate = "submitted_date"
        case completedBy = "completed_by"
        case completedDate = "completed_date"
        case extendDate = "extend_date"
        case editedBy = "edited_by"
        case editedDate = "edited_date"
        case status, autotask, isdelete, timestamp
        case assignedMember = "assigned_member"
        case teamName = "team_name"
        case gemID = "gem_id"
        case gemName = "gem_name"
        case ticketName = "ticket_name"
        case ticketTypeName = "ticket_type_name"
        case ableToDelete = "able_to_delete"
        case assignedForMe = "assigned_for_me"
        case priorityFlag = "priority_flag"
        case taskTypeFlag = "task_type_flag"
        case comments, notification, reminder
        case acceptOrDecline = "accept_or_decline"
        case availableStatus = "available_status"
        case editedUserName = "edited_user_name"
    }

    required init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        memberID = try values.decodeIfPresent(String.self, forKey: .memberID)
        groupID = try values.decodeIfPresent(String.self, forKey: .groupID)
        //...... etc.
    }
}

// MARK: - AvailableStatus
class AvailableStatus: Codable {
    let id: Int
    let name, displayName, icon: String

    enum CodingKeys: String, CodingKey {
        case id, name
        case displayName = "display_name"
        case icon
    }

    required init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        id = try values.decodeIfPresent(Int.self, forKey: .id)
        //...... etc.
    }
}
  • Thank you so much for answering me this. Btw //...... etc -> it means I need to list out all the values with try right? – myapp store Sep 19 '19 at 19:02
  • This solution handles null values but not values that can have different types, e.g Int or String – Joakim Danielson Sep 19 '19 at 19:07
  • @Jordy Gonzalez Error at `init - > 'required' initializer in non-class type 'DataClass'` – myapp store Sep 19 '19 at 19:08
  • sorry, I forgot to change "struct" for "class", if you change this should work – Jordy Gonzalez Sep 19 '19 at 19:45
  • A much easier solution is to remove the `required` keyword. – Joakim Danielson Sep 19 '19 at 19:50
  • @JordyGonzalez Thanks I will check it and update you here – myapp store Sep 20 '19 at 03:11
  • @JordyGonzalez I am getting two errors now `Value of optional type 'String?' must be unwrapped to a value of type 'String'` at the line `try values.decodeIfPresent(String.self, forKey: .memberID)` and `Use of unresolved identifier 'FSMatchAdditionalInfoType'` at the line `(FSMatchAdditionalInfoType.self, forKey: .groupID)` – myapp store Sep 20 '19 at 03:14
  • @JordyGonzalez also showing another one error `Return from initializer without initializing all stored properties` at the line `required init { }` – myapp store Sep 20 '19 at 03:17
  • @myappstore “Value of optional type 'String?' must be unwrapped...” you are getting this error because this answer is not relevant to your issue. – Joakim Danielson Sep 20 '19 at 07:10
  • FSMatchAdditionalInfoType can be your data type for example int.self, string.self. etc. – Jordy Gonzalez Sep 20 '19 at 21:59