Question: My iOS app has a pretty common setup: it makes HTTP queries to an API server that responds with JSON objects. These JSON objects are then parsed to appropriate Swift objects.

Initially I divided properties into required properties and optional properties, mostly based on my API server's database requirements. For example, `id`, `email`, and `name` are require fields so they use non-optional types. Others can be `NULL` in database, so they are optional types.

```
class User {
  let id: Int
  let email: String
  let profile: String?
  let name: String
  let motive: String?
  let address: String?
  let profilePhotoUrl: String?
}

```

Recently, I started wondering whether this was a good setup at all. I found out that although some properties might be always in the database, that does not mean that those properties will always be included in the JSON response. 

For example, in the User profile page, all these fields are needed to properly display the view. Therefore, JSON response will include all these fields. For a view that lists users' names, however, I would not need `email` or `id`, and JSON response should probably not include those properties either. Unfortunately, this will cause error and crash the app when parsing JSON response into Swift object since the app expects `id`, `email`, `name` to be always not-nil.

I'm thinking of changing all properties of Swift objects into optionals, but it feels like throwing away all the benefits of this language-specific feature. Moreover, I will have to write many more lines of code to unwrap all these optionals somewhere else in the app anyway.

On the other hand, JSON objects are by their nature not very interoperable with strict static typing and nil-checking of Swift so it might be better to simply accept that annoyance. 

Should I transition to models with every property as optionals? Or is there a better way? I'd appreciate any comment here.

Answer: 
There are three ways you can go with this:

1. Always send all the JSON data, and leave your properties non-optional.
2. Make all the properties optional.
3. Make all the properties non-optional, and write your own `init(from:)` method to assign default values to missing values, as described in [this answer](https://stackoverflow.com/a/44575580/7258538).

All of these should work; which one is "best" is opinion-based, and thus out of the scope of a Stack Overflow answer. Choose whichever one is most convenient for your particular need.
The first thing to do is ask: Does an element of the “view that lists users' names” need to be the same kind of object as the model object behind a “User profile page”? Perhaps not. Maybe you should create a model specifically for the user list:

```
struct UserList: Decodable {

    struct Item: Decodable {
        var id: Int
        var name: String
    }

    var items: [Item]

}

```

(Although the question said the JSON response might not include `id`, it doesn't seem like a user list without ids with be particularly useful, so I made it required here.)

If you really want them to be the same kind of object, then maybe you want to model a user as having core properties that the server always sends, and a “details” field that might be nil:

```
class User: Decodable {
    let id: Int
    let name: String
    let details: Details?

    struct Details: Decodable {
        var email: String
        var profile: String?
        var motive: String?
        var address: String?
        var profilePhotoUrl: String?
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decode(Int.self, forKey: .id)
        name = try container.decode(String.self, forKey: .name)
        details = container.contains(.email) ? try Details(from: decoder) : nil
    }

    enum CodingKeys: String, CodingKey {
        case id
        case name

        case email // Used to detect presence of Details
    }
}

```

Note that I create the `Details`, if it's present, using `Details(from: decoder)`, instead of the usual `container.decode(Details.self, forKey: .details)`. I do it using `Details(from: decoder)` so that the properties of the `Details` come out of the same JSON object as the properties of the `User`, instead of requiring a nested object.