---
title: Leveraging Structs and Generics in the Networking Layer with Swift 4
description: "Swift Talk #1 and #8 introduces an approach (hereinafter al"
---

[Blog ](https://www.metaltoad.com/blog)

# [Leveraging Structs and Generics in the Networking Layer with Swift 4](https://www.metaltoad.com/blog/leveraging-structs-and-generics-networking-layer-swift-4)

 Written by [Metal Toad Staff](https://www.metaltoad.com/blog/author/metal-toad-staff) | Oct 23, 2017 12:00:00 AM

 Filed under:

- [Apple/iOS](https://www.metaltoad.com/help/apple-ios)

Swift Talk [#1](https://talk.objc.io/episodes/S01E01-networking) and [#8](https://talk.objc.io/episodes/S01E08-networking-post-requests) introduces an approach (hereinafter alternative approach) to using structs and generics to build a networking layer in `Foundation`.

The original code was written in Swift 2.2. Here, I will make an update for Swift 4, incorporating the use of newly available JSON parsing features. I will also show how it could be extended to fetch images.

### The Swift Talk Approach

Let's say you have a simple JSON response:

```
{
    "name": "Metal Toad"
}
```

You can represent this response in a Swift struct:

```
struct Company: Decodable {
    let name: String
}
```

With the alternative approach, making a network call is as easy as:

```
let resource = Resource<Company>(method: .get, url: <URL>)
Networking().load(resource: resource) { response in 
    guard let name = response?.name else { return }
    print(name)  // "Metal Toad"
}
```

First, we create a resource object that is type specific to the `Company` struct specifying the HTTP method and url.

Second, we initialize our `Networking` class and call `load` with the resource as the parameter.

Just like magic we receive a response of type `Company` that was specified when constructing our resource object.

One of the benefits to this approach is a guarantee that the response will be of type `Company`. Also, the response object is provided in a completion closure next to the place where the method is called, thereby improving locality of reasoning.

### JSON Decoding before Swift 4

Network responses return static byte buffers encapsulated by the `Data` struct (or `NSData` if using reference semantics). Let's discuss how we convert the byte buffer into our `Company` struct.

Before Swift 4, we used `JSONSerialization.jsonObject` to convert `Data` into an object of type `[String: AnyObject]`.

```
//static byte buffer from a network request
let data: Data
let json: [String: AnyObject] = try? JSONSerialization.jsonObject(with: data, options: [])
```

Next, we need a function to look at values in the JSON object and mapping them to the response object. It checks whether the JSON has the expected keys, and whether values conform to their expected types in the response object.

```
extension Company {
    func parseJSON(dictionary: [String: AnyObject]) {
        guard let id = dictionary["name"] as? String else { return nil }
        self.name = name
    }
}
```

### Enter Swift 4's `JSONDecoder`

Swift 4 introduces a new interface for JSON decoding. We no longer need a `parseJSON` function to process `[String: AnyObject]`. Instead, we can directly go from `Data` to our target object, in this case `Company`.

Before we had to define the parse function of the `Resource` struct on a case by case basis, specifying the steps needed to transform `Data` into the response object.

```
struct Resource<A> {
    let url: URL
    let parse: (Data) -> A?
}
```

With Swift 4, we no longer need to define a parse function on a case by case basis. Instead, we can statically define it generically over any return type that conforms to `Decodable` in our `Resource` object.

Let's take a look at `JSONDecoder().decode(_:from:)`:

```
func decode<T>(_ type: T.Type, from data: Data) throws -> T where T : Decodable
```

This method takes `Data` as an argument and is generic over the return type, as long as the return type conforms to the protocol `Decodable`.

```
struct Resource<A> where A: Decodable {
    let url: URL
    let parse: (Data) -> A? = { data in return try? JSONDecoder().decode(A.self, from: data) }
}
```

Therefore, the use of this method is perfect for integrating into the `Resource` object of the alternative approach, since it is also generic over the return type. Another benefit is a check that the model we are asking for comforms to `Decodable`, otherwise it will fail at compile time.

### Image Resource

The alternative approach can also be extended to support the fetching of image resources. Like JSON resources above, image data comes back as static byte buffers in `Data`. To make it useful we simply need to use `UIImage.init?(data: Data)`. Therefore we define a new `ImageResource` object.

```
struct ImageResource {
    let url: URL
    let method: HttpMethod<Data>
    let parse: (Data) -> UIImage?
}
 
extension ImageResource {
    init(imageUrl: URL) {
        self.url = imageUrl
        self.method = .get
        self.parse = { data in return UIImage(data: data) }
    }
}
```

`ImageResource` now holds everything we need to fetch and parse data into a useful instance of UIImage.

### Playground

Please see this [gist](https://gist.github.com/ptseng/85f0aa8acbf48c0a64a68f4e44081a4d) for a Swift playground where we make networking calls to fetch a JSON resource, to post a request with a JSON body, and fetch a simple image resource.

### Conclusion

Swift 4's new JSON processing features enhances the alternative approach by removing the requirement of specifying a custom JSON parsing method for each custom type, as long as it conforms to `Decodable` as required by `JSONDecoder`. Furthermore, the alternative approach is flexible enough to be extended to other types of network calls, like the fetching of images.

This is my own personal exploration into this alternative approach. Suggestions for improvements, especially in how this approach can be further optimized, is welcomed.

[View full post](https://www.metaltoad.com/blog/leveraging-structs-and-generics-networking-layer-swift-4)

```json
{
  "@context" : "http://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Metal Toad Staff"
  },
  "dateModified" : "2023-12-06T23:26:47.627Z",
  "datePublished" : "2017-10-23T00:00:00Z",
  "headline" : "Leveraging Structs and Generics in the Networking Layer with Swift 4",
  "image" : {
    "@type" : "ImageObject",
    "height" : 500,
    "url" : "https://6104926.fs1.hubspotusercontent-na1.net/hubfs/6104926/Imported_Blog_Media/apple-blog-header-Aug-11-2023-10-04-11-8570-PM.png",
    "width" : 870
  },
  "mainEntityOfPage" : "https://www.metaltoad.com/blog/leveraging-structs-and-generics-networking-layer-swift-4",
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "height" : 60.0,
      "url" : "https://6104926.fs1.hubspotusercontent-na1.net/hubfs/6104926/social-suggested-images/6104926.fs1.hubspotusercontent-na1.nethub6104926hubfsMetal_Toad_Logo_orange_horizontal-50-1.jpg",
      "width" : 240.00002
    },
    "name" : "Blog"
  }
}
```