Search code examples
jsonswiftswifty-jsoninvalidation

Invalid type in JSON write (.SurveyAnswer) - SwiftyJSON


Something must be wrong in my model because my project fails with this error whenever this function runs.

func communityGroupPost(postUtil: PostShareUtil, success: @escaping (ResultModel<BaseModel>) -> Void, fail: @escaping (ErrorModel) -> Void) {
        let url = "CommunityGroup/CommunityGroupPost"
        manager.post(url, bodyParameters: postUtil.toDictionary(), success: success, fail: fail).setJsonKey(nil).fetch()
    }

The problem says Rtuk.SurveyAnswer but I could not understand what is wrong with SurveyAnswer model. I am appending surveyAnswers for all Json values.

Thanks in advance for the help.

Any ideas?

import Foundation
import Networking
import SwiftyJSON
class SurveySummary: Serializable {
        var question: String?
        var surveyAnswers: [SurveyAnswer]?
        var surveyTypeId: Int?
        var order: Int!
        
        init(question: String, surveyAnswers: [SurveyAnswer], surveyTypeId: Int, order: Int) {
            self.question = question
            self.surveyAnswers = surveyAnswers
            self.surveyTypeId = surveyTypeId
            self.order = order
        }
        
        enum CodingKeys: String, CodingKey {
            case question
            case surveyAnswers
            case surveyTypeId
            case order
        }
        
        required init(from decoder: Decoder) throws {
            let values = try decoder.container(keyedBy: CodingKeys.self)
            question = try values.decodeIfPresent(String.self, forKey: .question)
            surveyAnswers = try values.decodeIfPresent([SurveyAnswer].self, forKey: .surveyAnswers)
            surveyTypeId = try values.decodeIfPresent(Int.self, forKey: .surveyTypeId)
            order = try values.decodeIfPresent(Int.self, forKey: .order)
        }
        
        func encode(to encoder: Encoder) throws {
            var values = encoder.container(keyedBy: CodingKeys.self)
            try values.encodeIfPresent(question, forKey: .question)
            try values.encodeIfPresent(surveyAnswers, forKey: .surveyAnswers)
            try values.encodeIfPresent(surveyTypeId, forKey: .surveyTypeId)
            try values.encodeIfPresent(order, forKey: .order)
        }
        
        init(withJSON json: JSON) {
            question = json["question"].string
            surveyAnswers = []
            json["surveyAnswers"].arrayValue.forEach { json in
                self.surveyAnswers?.append(SurveyAnswer(withJSON: json))
            }
            surveyTypeId = json["surveyTypeId"].intValue
            order = json["order"].intValue
        }
    }
    
    extension SurveySummary {
        func convertToDictionary() -> NSDictionary {
            let dictionary = NSMutableDictionary()
            dictionary["question"] = question
            dictionary["surveyTypeId"] = surveyTypeId
            dictionary["surveyAnswers"] = surveyAnswers
            dictionary["order"] = order
            return dictionary
        }
    }

And this is my PostShareUtil

final class PostShareUtil {
    // MARK: - Properties
    var surveys: [SurveySummary]?
    var pinnedUntilAsTimestamp: Double?
    var postType: Int?
  
    // MARK: - Survey Create
    init(group: CommunityGroupModel?, postDesc: String, surveys: [SurveySummary], setting: PostShareSetting, pinnedUntilAsTimestamp: Double, postType: Int) {
        self.group = group
        self.postDesc = postDesc
        self.surveys = surveys
        self.setting = setting
        self.pinnedUntilAsTimestamp = pinnedUntilAsTimestamp
        self.postType = postType
    }

Solution

  • The problem was in convertToDictionary func for surveyAnswers. If changed to below code it works fine

    extension SurveySummary {
        func convertToDictionary() -> NSDictionary {
            let dictionary = NSMutableDictionary()
            dictionary["question"] = question
            dictionary["surveyTypeId"] = surveyTypeId
            if surveyAnswers != nil {
                let jsonDict = surveyAnswers!.map { $0.convertToDictionary() }
                dictionary["surveyAnswers"] = jsonDict
            }
            dictionary["order"] = order
            return dictionary
        }
    }