0

I got this class:

import Foundation

class Own: Codable {
    let response: Ownerinfo

    init(response: Ownerinfo) {
        self.response = response
    }
}

class Ownerinfo: Codable {
    let gender, firstName, email, country: String
    let dob: String
    let conections: [JSONAny]
    let lastName, token, phoneNumber: String
    let image: String
    let id: String

    enum CodingKeys: String, CodingKey {
        case gender
        case firstName = "first_name"
        case email, country, dob, conections
        case lastName = "last_name"
        case token, phoneNumber, image, id
    }

    init(gender: String, firstName: String, email: String, country: String, dob: String, conections: [JSONAny], lastName: String, token: String, phoneNumber: String, image: String, id: String) {
        self.gender = gender
        self.firstName = firstName
        self.email = email
        self.country = country
        self.dob = dob
        self.conections = conections
        self.lastName = lastName
        self.token = token
        self.phoneNumber = phoneNumber
        self.image = image
        self.id = id
    }
}


// MARK: - Encode/decode helpers

class JSONNull: Codable, Hashable {

    public static func == (lhs: JSONNull, rhs: JSONNull) -> Bool {
        return true
    }

    public var hashValue: Int {
        return 0
    }

    public init() {}

    public required init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if !container.decodeNil() {
            throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull"))
        }
    }

    public func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encodeNil()
    }
}

class JSONCodingKey: CodingKey {
    let key: String

    required init?(intValue: Int) {
        return nil
    }

    required init?(stringValue: String) {
        key = stringValue
    }

    var intValue: Int? {
        return nil
    }

    var stringValue: String {
        return key
    }
}

class JSONAny: Codable {

    let value: Any

    static func decodingError(forCodingPath codingPath: [CodingKey]) -> DecodingError {
        let context = DecodingError.Context(codingPath: codingPath, debugDescription: "Cannot decode JSONAny")
        return DecodingError.typeMismatch(JSONAny.self, context)
    }

    static func encodingError(forValue value: Any, codingPath: [CodingKey]) -> EncodingError {
        let context = EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode JSONAny")
        return EncodingError.invalidValue(value, context)
    }

    static func decode(from container: SingleValueDecodingContainer) throws -> Any {
        if let value = try? container.decode(Bool.self) {
            return value
        }
        if let value = try? container.decode(Int64.self) {
            return value
        }
        if let value = try? container.decode(Double.self) {
            return value
        }
        if let value = try? container.decode(String.self) {
            return value
        }
        if container.decodeNil() {
            return JSONNull()
        }
        throw decodingError(forCodingPath: container.codingPath)
    }

    static func decode(from container: inout UnkeyedDecodingContainer) throws -> Any {
        if let value = try? container.decode(Bool.self) {
            return value
        }
        if let value = try? container.decode(Int64.self) {
            return value
        }
        if let value = try? container.decode(Double.self) {
            return value
        }
        if let value = try? container.decode(String.self) {
            return value
        }
        if let value = try? container.decodeNil() {
            if value {
                return JSONNull()
            }
        }
        if var container = try? container.nestedUnkeyedContainer() {
            return try decodeArray(from: &container)
        }
        if var container = try? container.nestedContainer(keyedBy: JSONCodingKey.self) {
            return try decodeDictionary(from: &container)
        }
        throw decodingError(forCodingPath: container.codingPath)
    }

    static func decode(from container: inout KeyedDecodingContainer<JSONCodingKey>, forKey key: JSONCodingKey) throws -> Any {
        if let value = try? container.decode(Bool.self, forKey: key) {
            return value
        }
        if let value = try? container.decode(Int64.self, forKey: key) {
            return value
        }
        if let value = try? container.decode(Double.self, forKey: key) {
            return value
        }
        if let value = try? container.decode(String.self, forKey: key) {
            return value
        }
        if let value = try? container.decodeNil(forKey: key) {
            if value {
                return JSONNull()
            }
        }
        if var container = try? container.nestedUnkeyedContainer(forKey: key) {
            return try decodeArray(from: &container)
        }
        if var container = try? container.nestedContainer(keyedBy: JSONCodingKey.self, forKey: key) {
            return try decodeDictionary(from: &container)
        }
        throw decodingError(forCodingPath: container.codingPath)
    }

    static func decodeArray(from container: inout UnkeyedDecodingContainer) throws -> [Any] {
        var arr: [Any] = []
        while !container.isAtEnd {
            let value = try decode(from: &container)
            arr.append(value)
        }
        return arr
    }

    static func decodeDictionary(from container: inout KeyedDecodingContainer<JSONCodingKey>) throws -> [String: Any] {
        var dict = [String: Any]()
        for key in container.allKeys {
            let value = try decode(from: &container, forKey: key)
            dict[key.stringValue] = value
        }
        return dict
    }

    static func encode(to container: inout UnkeyedEncodingContainer, array: [Any]) throws {
        for value in array {
            if let value = value as? Bool {
                try container.encode(value)
            } else if let value = value as? Int64 {
                try container.encode(value)
            } else if let value = value as? Double {
                try container.encode(value)
            } else if let value = value as? String {
                try container.encode(value)
            } else if value is JSONNull {
                try container.encodeNil()
            } else if let value = value as? [Any] {
                var container = container.nestedUnkeyedContainer()
                try encode(to: &container, array: value)
            } else if let value = value as? [String: Any] {
                var container = container.nestedContainer(keyedBy: JSONCodingKey.self)
                try encode(to: &container, dictionary: value)
            } else {
                throw encodingError(forValue: value, codingPath: container.codingPath)
            }
        }
    }

    static func encode(to container: inout KeyedEncodingContainer<JSONCodingKey>, dictionary: [String: Any]) throws {
        for (key, value) in dictionary {
            let key = JSONCodingKey(stringValue: key)!
            if let value = value as? Bool {
                try container.encode(value, forKey: key)
            } else if let value = value as? Int64 {
                try container.encode(value, forKey: key)
            } else if let value = value as? Double {
                try container.encode(value, forKey: key)
            } else if let value = value as? String {
                try container.encode(value, forKey: key)
            } else if value is JSONNull {
                try container.encodeNil(forKey: key)
            } else if let value = value as? [Any] {
                var container = container.nestedUnkeyedContainer(forKey: key)
                try encode(to: &container, array: value)
            } else if let value = value as? [String: Any] {
                var container = container.nestedContainer(keyedBy: JSONCodingKey.self, forKey: key)
                try encode(to: &container, dictionary: value)
            } else {
                throw encodingError(forValue: value, codingPath: container.codingPath)
            }
        }
    }

    static func encode(to container: inout SingleValueEncodingContainer, value: Any) throws {
        if let value = value as? Bool {
            try container.encode(value)
        } else if let value = value as? Int64 {
            try container.encode(value)
        } else if let value = value as? Double {
            try container.encode(value)
        } else if let value = value as? String {
            try container.encode(value)
        } else if value is JSONNull {
            try container.encodeNil()
        } else {
            throw encodingError(forValue: value, codingPath: container.codingPath)
        }
    }

    public required init(from decoder: Decoder) throws {
        if var arrayContainer = try? decoder.unkeyedContainer() {
            self.value = try JSONAny.decodeArray(from: &arrayContainer)
        } else if var container = try? decoder.container(keyedBy: JSONCodingKey.self) {
            self.value = try JSONAny.decodeDictionary(from: &container)
        } else {
            let container = try decoder.singleValueContainer()
            self.value = try JSONAny.decode(from: container)
        }
    }

    public func encode(to encoder: Encoder) throws {
        if let arr = self.value as? [Any] {
            var container = encoder.unkeyedContainer()
            try JSONAny.encode(to: &container, array: arr)
        } else if let dict = self.value as? [String: Any] {
            var container = encoder.container(keyedBy: JSONCodingKey.self)
            try JSONAny.encode(to: &container, dictionary: dict)
        } else {
            var container = encoder.singleValueContainer()
            try JSONAny.encode(to: &container, value: self.value)
        }
    }
}

and i save it as a string in coredata entity knowing it is wrong to do so

enter image description here

And I want to save it in CoreData container in http post func inside it :

      do {
        // create json object from data or use JSONDecoder to convert to Model stuct
          if let jsonResponse = try JSONSerialization.jsonObject(with: responseData, options: .mutableContainers) as? Dictionary<String,Any>{
          print(jsonResponse)
            let decoder = JSONDecoder()
            do {
                let loginResponse = try decoder.decode(Own.self, from: responseData)
                print("firstName:", loginResponse.response.firstName)
                let owner = Owner(context: self.persistentContainer.viewContext)
                owner.id = loginResponse.response.id
                owner.firstName = loginResponse.response.firstName
                owner.lastName  =  loginResponse.response.lastName
                owner.email = loginResponse.response.email
                owner.gender = loginResponse.response.gender
                owner.phoneNumber = loginResponse.response.phoneNumber
                owner.dob = loginResponse.response.dob
                owner.country = loginResponse.response.country
                owner.token = loginResponse.response.token
                owner.image = loginResponse.response.image
                owner.conections = loginResponse.response.conections[0] as? String /// the problem is here how can i get the JsonAny 
if this is the only way to extract json response and save to coredata
                
                do {
                    try self.persistentContainer.viewContext.save()
                } catch {
                    print("Failed to save event \(error)")
                }
                DispatchQueue.main.async {
                    self.myuser = loginResponse
                                    }
                
          
                } catch {
                 print(error)
             }
          // handle json response

the idea i want to save that JsonAny into CoreData ? how can i save it ?

if i tried to save it like i did it says Cast from 'JSONAny' to unrelated type 'String' always fails any idea how can i do it ?

koen
  • 5,383
  • 7
  • 50
  • 89
Aber R
  • 37
  • 1
  • 7
  • 1
    Maybe this helps: https://stackoverflow.com/a/52698618/1619193 – Shawn Frank Mar 17 '22 at 13:29
  • 1
    This appears to get messy in at least two places. First you suddenly introduce a magic `JSONArray` which appears to be a random piece of JSON. This is defeating the point of a structured `Codable` approach more or less completely. Second there is the introduction of `JSONSerialization` which is what we want to avoid at all cost if we go the `Codable` route. It appears all of what you are trying to achieve would be rather simple if only your `Connection` information would be some structured piece of data instead of a random string of JSON? – Patru Mar 21 '22 at 01:05
  • if you want to use http you have to use Jsonserialization else you will end up with swifttJson and alamofire and that is not better than http, that is my point, more over my json data is not quoted, so that is the best safe way to do so – Aber R Mar 21 '22 at 09:27

0 Answers0