0

I have different structs as my dataModels. when i want to parse data with JsonDecoder().decode i need set a .Type.self in .decoder(SomeType.self , from: data)

I want write a support function which can return right Type respectively. something like this But I don't know how...

func check<T>(string: String) -> T
if string == "something" {
return Something.type
}

func parseJSON(from data: Data , with address: String)-> Codable? {
let type = check(string: address) 
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(type.self, from: data)
return decodedData
} catch let error {
print(error)
return nil
}
}

WHEN I WRITE THE code below, Everything works fine. But I always have to write parseJSON func with little difference over and over again

  func fetch(from adress: String) {
        guard let url = URL(string: adress) else {print("can't get URL from current urlAdress"); return}
        let json = makeHttpBody(from: adress)
        let jsonData = try? JSONSerialization.data(withJSONObject: json)
        var request = URLRequest(url: url , cachePolicy: .useProtocolCachePolicy)
        request.httpMethod = K.post
        request.setValue(K.contentType, forHTTPHeaderField:K.applicationJson)
        request.timeoutInterval = Double.infinity
        request.httpBody = jsonData
        
        let session = URLSession(configuration: .default)
        let task = session.dataTask(with: request) { (data, responce, error) in
            if error != nil {
                print(error!.localizedDescription)
            }
            if let safeData = data {
            
                if adress == K.balanceUrl {
                if let parsedData = self.parseJsonBalance(from: safeData) {
                    self.delegate?.didUpdateData(with: self, with: parsedData)
                }
                } else if adress == K.projectsUrl {
                    if let parsedData = self.parseJsonProject(from: safeData) {
                        self.delegate?.didUpdateData(with: self, with: parsedData)
                    }
                }
            }
        }
        task.resume()
    }

  func makeHttpBody(from StringData: String) -> [String: Any] {
        switch StringData {
        case K.balanceUrl:
            return K.authorization
        case K.projectsUrl:
            return K.projects
        default:
            return ["none" : "none"]
        }
    }
1
  • 1
    You have a string telling you what type to decode? Suppose you were able to do this, how do you intend on using the decoded thing returned by parseJSON? All you know about it is that it is Codable. You won't be able to do much with it, will you? Commented Mar 11, 2021 at 9:51

1 Answer 1

3

Your approach cannot work, you have to use a generic type constrained to Decodable. Checking for strings at runtime is not a good practice.

This is a reduced version of your code, the error is handed over to the caller

func parseJSON<T : Decodable>(from data: Data) throws -> T {
    return try JSONDecoder().decode(T.self, from: data)
}

Then you can write (the return type must be annotated)

let result : [Foo] = try parseJSON(from: data)

Or if you want to specify the type in the function

func parseJSON<T : Decodable>(from data: Data, type : T.Type) throws -> T {
    return try JSONDecoder().decode(T.self, from: data)
}

let result = try parseJSON(from: data, type: [Foo].self)
Sign up to request clarification or add additional context in comments.

1 Comment

sorry, I could not understand your answer, but I supplemented my question with a code with which everything works the way I want, but this causes code duplication

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.