narner
narner

Reputation: 3221

Mapping a variety of JSON responses with the same top - level structure in Swift

I have a variety of JSON responses that I'm getting back from a server via Alamofire; two are included below:

1)

{
  "json" : {
    "harkUpdate" : {
      "more" : [
        {
          "unread-count" : {
            "last" : 1613507864973,
            "index" : {
              "graph" : {
                "graph" : "\/ship\/~dopzod\/urbit-help",
                "index" : "\/"
              }
            }
          }
        },
        {
          "seen-index" : {
            "index" : {
              "graph" : {
                "index" : "\/",
                "graph" : "\/ship\/~dopzod\/urbit-help"
              }
            },
            "time" : 1613507864973
          }
        }
      ]
    }
  },
  "response" : "diff",
  "id" : 3
}
    {
      "json" : {
        "graph-update" : {
          "keys" : [
            {
              "name" : "book-club-4717",
              "ship" : "sicdev-pilnup"
            },
            {
              "name" : "dm--locrev-finlys",
              "ship" : "haddef-sigwen"
            },
            {
              "name" : "smol-bibliotheca",
              "ship" : "dasfeb"
            },
            {
              "name" : "interface",
              "ship" : "bitpyx-dildus"
            },
            {
              "name" : "jobs-gigs",
              "ship" : "nibset-napwyn"
            },
            {
              "name" : "tlon-general",
              "ship" : "bolbex-fogdys"
            }
          ]
        }
      },
      "id" : 1,
      "response" : "diff"
    }

As you can see, they both have an id, a response, and json fields - but the actual json response in them varies.

Normally what I would do is generate classes using something like quicktype.io, or use one of the many ObjectMapping frameworks out there. What I'm trying to get mentally un-blocked with is that all these json responses have a field called "json", which has a different structure. I'm trying to figure out who I can make unique classes for the responses given this structuring. Any help appreciated.

Upvotes: 0

Views: 729

Answers (1)

πter
πter

Reputation: 2217

You can declare a basic object which's json property will be a generic type conforming to Codable.

struct JSON<T : Codable>: Codable {
    let json: T
    let id: Int
    let response: String
}

After you define two structs which will represent the first and second json objects. For simplicity I will define only the objects that represent the second JSON:

struct GraphUpdate: Codable {
    let graphUpdate: Keys

    enum CodingKeys: String, CodingKey {
        case graphUpdate = "graph-update"
    }
}

struct Keys: Codable {
    let keys: [Key]
}

struct Key: Codable {
    let name, ship: String
}

And when trying to decode, you have to specify what object you want to decode to:

let item = try? JSONDecoder().decode(JSON<GraphUpdate>.self, from: data)

Upvotes: 4

Related Questions