0

Having troubles getting this to work: I am trying to abstract the JSON-decoding into a function, taking as arguments a Codable plus some Data.

Therefore, I need to have the following function-signature if possible for this:

func doTheJSONDecoding(cdbl: Codable, data: Data) {...}

Here is my code, starting with the data-model. There are two examples below....

import UIKit
import Foundation

struct MyStructCodable : Codable {
    let items : [MyValue]?
}

struct MyValue : Codable {
    let value : String?
}

let dta: Data = """
{
  "items": [
    {
      "value": "Hello1"
    }
  ]
}
""".data(using: .utf8)!

Then the two examples:

// Example 1: this code works fine !!!!!!!!!!!!!!!!!!!!!!!!

let decoder = JSONDecoder()
do {
    let result = try decoder.decode(MyStructCodable.self, from: dta)
    print(result.items?[0].value ?? "")
} catch {
    print(error)
}

// above code prints:   Hello1


// Example 2: this code does not work - WHY ???????????????

func doTheJSONDecoding(cdbl: Codable, data: Data) {
    let decoder = JSONDecoder()
    do {
        let result = try decoder.decode(cdbl, from: data)
        print(result.items?[0].value ?? "")
    } catch {
        print(error)
    }
}

let myValue = MyValue(value: "Hello2")
let myStructyCodable = MyStructCodable(items: [myValue])
doTheJSONEncoding(cdbl: myStructyCodable, data: dta)

The error thrown is inside the function, it says:

enter image description here

Is there any way so that I can keep the function signature (i.e. func doTheJSONDecoding(cdbl: Codable, data: Data) and still getting this to work ?? Any help appreciated.

iKK
  • 6,394
  • 10
  • 58
  • 131
  • Ok, I clarified inside the example and renamed the function to `doTheJSONDecoding()` instead. - I clearly would like to decode (not encode) - therefore I need to keep JSONDecoder I think. (i.e. I do have JSON-data and I would like to decode it into a struct). Moreover, changing the function signature to `doTheJSONDecoding(cable: Decodable, data: Data)` does not help either...) – iKK Dec 02 '18 at 14:54
  • 1
    `cdbl` must be a concrete type, not the protocol. You can use the protocol as a constraint of a generic.And not any type conforming to `Codable` has `items`. – vadian Dec 02 '18 at 14:56
  • @vadian: Thanks, ah I see, the type is required - not the conformance. So, I guess, there is NO WAY to abstract any kind of type that conforms to Decodable (or Codable in general) - am I right on this ? If no - how would I still do it ? – iKK Dec 02 '18 at 15:04
  • https://stackoverflow.com/a/51058460/6630644 – SPatel Dec 02 '18 at 17:39

1 Answers1

2

Here is my attempt to get your func to work, it can probably be improve but it does return a properly decoded object. Note that it takes the type of object rather than an object and it is that type T that implement Decodable.

func doTheJSONEncoding<T: Decodable>(cdbl: T.Type, data: Data) -> T? {
    let decoder = JSONDecoder()
    do {
        let result = try decoder.decode(cdbl.self, from: data)
        return result
    } catch {
        print(error)
    }
    return nil
}

//testing it
let myValue = MyValue(value: "Hello2")
let myStructyCodable = MyStructCodable(items: [myValue])
let decoded = doTheJSONEncoding(cdbl: MyStructCodable.self, data: dta)
print(decoded?.items?[0].value ?? "")
Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52