Swift 4 added the new Codable protocol. When I use JSONDecoder it seems to require all the non-optional properties of my Codable class to have keys in the JSON or it throws an error.

Making every property of my class optional seems like an unnecessary hassle since what I really want is to use the value in the json or a default value. (I don't want the property to be nil.)

Is there a way to do this?

class MyCodable: Codable {
    var name: String = "Default Appleseed"
}

func load(input: String) {
    do {
        if let data = input.data(using: .utf8) {
            let result = try JSONDecoder().decode(MyCodable.self, from: data)
            print("name: \(result.name)")
        }
    } catch  {
        print("error: \(error)")
        // `Error message: "Key not found when expecting non-optional type
        // String for coding key \"name\""`
    }
}

let goodInput = "{\"name\": \"Jonny Appleseed\" }"
let badInput = "{}"
load(input: goodInput) // works, `name` is Jonny Applessed
load(input: badInput) // breaks, `name` required since property is non-optional

推荐答案

Approach that I prefer is using so called DTOs - data transfer object. It is a struct, that conforms to Codable and represents the desired object.

struct MyClassDTO: Codable {
    let items: [String]?
    let otherVar: Int?
}

Then you simply init the object that you want to use in the app with that DTO.

 class MyClass {
    let items: [String]
    var otherVar = 3
    init(_ dto: MyClassDTO) {
        items = dto.items ?? [String]()
        otherVar = dto.otherVar ?? 3
    }

    var dto: MyClassDTO {
        return MyClassDTO(items: items, otherVar: otherVar)
    }
}

This approach is also good since you can rename and change final object however you wish to. It is clear and requires less code than manual decoding. Moreover, with this approach you can separate networking layer from other app.

Json相关问答推荐

从Json响应中为需要每个值的Post请求提取多个值

为什么JQ筛选器不将原始输入打印为$var|.';文档?

如何在Swift中使用JSON编码器的泛型

无法使用Jolt变换在嵌套的JSON中提取值

数据到jsonObject到数据到 struct 是可能的吗?

将pyspark.sql.Rowtype数据转换为Json字符串,消除Azure Databricks NB中的值

在 postgres 14 中将记录转换为所需的 json 格式

如何使用jolt规范将一个对象添加到另一个对象中并删除该对象

将具有多个级别的 json 读入 DataFrame [python]

jq:来自嵌套 JSON 的映射

Go - JSON 验证抛出错误,除非我在 struct 中使用指针.为什么?

如何将从嵌套 Select 返回的空值转换为空数组?

Android JSON 库的性能和可用性比较

是否可以将数据写入本地 json 文件,除了Angular 之外什么都没有?

从 VS 2017 Azure Function 开发中的 local.settings.json 读取值

Peewee 模型转 JSON

Gson 将一组数据对象转换为 json - Android

无法将空值放入 JSON 对象

Python 到 JSON 序列化在十进制上失败

JSON 格式的 Amazon S3 响应?