kye
kye

Reputation: 2246

Decoding a struct using a key from JSON swift4

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
    }

Upvotes: 2

Views: 632

Answers (1)

Luca Angeletti
Luca Angeletti

Reputation: 59496

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.

Upvotes: 2

Related Questions