2

Using Swift 4's Encoder & Decoder protocol and JSONDecoder how do I initialize a struct of type Codeable using a key from a given JSON.

i.e. Given the JSON below I wish to only use results to initialize Example

{
  "boolean": true,
  "number": 123,
  "results": {
    "a": "b",
    "c": "d",
    "e": "f"
  },
  "string": "Hello World"
}
struct Example: MDB, Codeable{
    var a: String
    var b: String
    var c: String
}
public static func initalize<T: Codable & MDBItem>(json: Data) -> [T]{
        var items = [T]()
        let decoder = JSONDecoder()
        do {
         //How do I initialize `T` using a key from the JSON given
          //ie. decoder.decode([T].self, from: json["results"])
          // Or decoder.decode(["results", [T].self, from: json)
            items = try decoder.decode([T].self, from: json)
                    } catch {
            print("error trying to convert data to JSON")
        }
        return items
    }
kye
  • 2,166
  • 3
  • 27
  • 41
  • Compare https://stackoverflow.com/q/44549310/2976878 & https://stackoverflow.com/q/44715494/2976878 – Hamish Jun 24 '17 at 10:49

1 Answers1

2

A possible easy way is creating a wrapper struct.

So, you have this JSON

let json = """
    {
    "boolean": true,
    "number": 123,
    "results": {
        "a": "b",
        "c": "d",
        "e": "f"
    },
    "string": "Hello World"
    }
    """

Since you are only interested into the "results" section you defined this struct

struct Example: Codable {
    let a: String
    let c: String
    let e: String
}

Wrapper

Now in order to leverage the power of the Codable protocol (available in Swift 4) you can create a wrapper struct like this

struct Wrapper: Codable {
    let results: Example
}

The only purpose of the Wrapper struct is to define a path from the root of the original JSON to the section you are interested in. This was the Codable protocol will do the rest of the job for you.

Decoding

Now you can use the Wrapper struct to easily decode the JSON.

if
    let data = json.data(using: .utf8),
    let wrapper = try? JSONDecoder().decode(Wrapper.self, from: data) {

    let results = wrapper.results
    print(results)
}

And finally you can extract the results property from the wrapper.

Luca Angeletti
  • 58,465
  • 13
  • 121
  • 148
  • Thanks for the answer, this should work. I'll just have to figure out a generic way to make it work with multiple structs. – kye Jun 25 '17 at 17:52