Trying to write a generic function for parsing JSON into codable Structs

泪湿孤枕 提交于 2021-02-17 04:45:43

问题


I'm currently parsing JSON like this

struct ExampleStruct : Codable {
     init() {

     }
     // implementation
}

if let jsonData = jsonString.data(using: .utf8) {
    do {
        let decoder = JSONDecoder()
        let object =  try decoder.decode(ExampleStruct.self, from: jsonData)
    } catch {
        print("Coding error - \(error)")
    }
}

This works fine, however I've been trying to learn about Generics over the weekend. I'm trying to write a method which I pass in a Codable struct type and a string of JSON which returns the object of type I want back.

I've tried the following :-

func getType<T>(_ anyType: T.Type, from jsonString:String) -> T? {

if let jsonData = jsonString.data(using: .utf8) {
    do {
        let decoder = JSONDecoder()
        let object =  try decoder.decode(anyType, from: jsonData)//Errors here
        return object as? T
        return nil
    } catch {
        print("Coding error - \(error)")
       return nil
    }
  }
return nil
}

and then when I want to do the above

 if let exampleStruct:ExampleStruct = getType(type(of: ExampleStruct()), from: jsonString) {
  print(exampleStruct)
 }

However on the let = object line I get the following errors

Cannot convert value of type 'T' (generic parameter of global function 'getType(:from:)') to expected argument type 'T' (generic parameter of instance method 'decode(:from:)')

and

In argument type 'T.Type', 'T' does not conform to expected type 'Decodable'

As I said I've just been trying to learn about generics this weekend but I've clearly hit a block in my understanding. Is there a fix for this, indeed is what I'm trying to do even possible or a good idea?


回答1:


First of all it's highly recommended to hand over an error of a throwing function to the caller.
Second of all Data created from an UTF8 string can never fail.

You have to constrain the generic type to Decodable, it's not needed to pass the type as extra parameter.

Your function can be reduced to

func getType<T : Decodable>(from jsonString:String) throws -> T {
    let jsonData = Data(jsonString.utf8)
    return try JSONDecoder().decode(T.self, from: jsonData)
}


来源:https://stackoverflow.com/questions/50909240/trying-to-write-a-generic-function-for-parsing-json-into-codable-structs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!