Skip to content

Commit

Permalink
在 Swift 中对 JSON 进行自定义编码和解码的小技巧 (#6967)
Browse files Browse the repository at this point in the history
* 更新测试

* Revert "更新测试"

This reverts commit afb007d.

* 8 个值得了解的树形数据结构 (#6804)

* 8个值得了解的树形数据结构

8个值得了解的树形数据结构

* Update 8-Useful-Tree-Data-Structures-Worth-Knowing.md

* Update 8-useful-tree-data-structures-worth-knowing.md

Co-authored-by: sun <776766759@qq.com>

* 眼动跟踪和移动世界的最佳用户体验实践 (#6806)

* 眼动跟踪和移动世界的最佳用户体验实践

翻译完成

* 眼动跟踪和移动世界的最佳用户体验实践 #6806

谢谢指点~@xionglong58     @fanyijihua 根据第一轮校对意见修改完成

* 眼动追踪和移动世界的最佳用户体验实践

* 眼动追踪和移动世界的最佳用户体验实践

* 我并不讨厌箭头函数(#6610) (#6659)

* 我并不讨厌箭头函数(#6610)

* 我并不讨厌箭头函数(#6610) - 根据校对结果修改

* Update i-dont-hate-arrow-functions.md

Co-authored-by: 小添 <xiaotian@qunhemail.com>
Co-authored-by: sun <776766759@qq.com>

* 掌握 JavaScript 面试:什么是纯函数? (#6828)

* 掌握 JavaScript 面试:什么是纯函数?

掌握 JavaScript 面试:什么是纯函数?

* Update master-the-javascript-interview-what-is-a-pure-function.md

* Update master-the-javascript-interview-what-is-a-pure-function.md

* Update master-the-javascript-interview-what-is-a-pure-function.md

* Update master-the-javascript-interview-what-is-a-pure-function.md

* Update master-the-javascript-interview-what-is-a-pure-function.md

* Update master-the-javascript-interview-what-is-a-pure-function.md

* Update master-the-javascript-interview-what-is-a-pure-function.md

Co-authored-by: lsvih <lsvih@qq.com>

* fix:文章翻译问题 (#6833)

* 用依赖注入来解耦你的代码 (#6823)

* translate(*): Part.1

* translate(*): Part.2

* translate(*): 完成翻译

* fix(*): 完成校对

* Create generator-functions-in-javascript.md (#6841)

* Create generator-functions-in-javascript.md

* Update generator-functions-in-javascript.md

* Create how-to-keep-your-dependencies-secure-and-up-to-date.md (#6843)

* Create how-to-keep-your-dependencies-secure-and-up-to-date.md

* Update how-to-keep-your-dependencies-secure-and-up-to-date.md

* Create deep-dive-into-react-fiber-internals.md (#6845)

* Create deep-dive-into-react-fiber-internals.md

* Update deep-dive-into-react-fiber-internals.md

* Update deep-dive-into-react-fiber-internals.md

* Update deep-dive-into-react-fiber-internals.md

* Create how-can-cloud-services-help-improve-your-businessess-efficiency.md (#6847)

* Create how-can-cloud-services-help-improve-your-businessess-efficiency.md

* Update how-can-cloud-services-help-improve-your-businessess-efficiency.md

* Create should-you-learn-vim-as-a-developer-in-2020.md (#6849)

* Go 发布新版 Protobuf API (#6827)

* Achieve translation

* 8 个值得了解的树形数据结构 (#6804)

* 8个值得了解的树形数据结构

8个值得了解的树形数据结构

* Update 8-Useful-Tree-Data-Structures-Worth-Knowing.md

* Update 8-useful-tree-data-structures-worth-knowing.md

Co-authored-by: sun <776766759@qq.com>

* 眼动跟踪和移动世界的最佳用户体验实践 (#6806)

* 眼动跟踪和移动世界的最佳用户体验实践

翻译完成

* 眼动跟踪和移动世界的最佳用户体验实践 #6806

谢谢指点~@xionglong58     @fanyijihua 根据第一轮校对意见修改完成

* 眼动追踪和移动世界的最佳用户体验实践

* 眼动追踪和移动世界的最佳用户体验实践

* 我并不讨厌箭头函数(#6610) (#6659)

* 我并不讨厌箭头函数(#6610)

* 我并不讨厌箭头函数(#6610) - 根据校对结果修改

* Update i-dont-hate-arrow-functions.md

Co-authored-by: 小添 <xiaotian@qunhemail.com>
Co-authored-by: sun <776766759@qq.com>

* 掌握 JavaScript 面试:什么是纯函数? (#6828)

* 掌握 JavaScript 面试:什么是纯函数?

掌握 JavaScript 面试:什么是纯函数?

* Update master-the-javascript-interview-what-is-a-pure-function.md

* Update master-the-javascript-interview-what-is-a-pure-function.md

* Update master-the-javascript-interview-what-is-a-pure-function.md

* Update master-the-javascript-interview-what-is-a-pure-function.md

* Update master-the-javascript-interview-what-is-a-pure-function.md

* Update master-the-javascript-interview-what-is-a-pure-function.md

* Update master-the-javascript-interview-what-is-a-pure-function.md

Co-authored-by: lsvih <lsvih@qq.com>

* Address comments

Co-authored-by: Amberlin1970 <37952468+Amberlin1970@users.noreply.github.com>
Co-authored-by: sun <776766759@qq.com>
Co-authored-by: Charlo <49369951+Charlo-O@users.noreply.github.com>
Co-authored-by: TiaossuP <tiaossup@yeah.net>
Co-authored-by: 小添 <xiaotian@qunhemail.com>
Co-authored-by: niayyy <yy761706@gmail.com>
Co-authored-by: lsvih <lsvih@qq.com>

* JSON.stringify() 的 5 个秘密特性 (#6793)

* Update 5-secret-features-of-json-stringify.md

* Update 5-secret-features-of-json-stringify.md

* Update 5-secret-features-of-json-stringify.md

* Update 5-secret-features-of-json-stringify.md

* Create high-speed-inserts-with-mysql.md (#6853)

* Create high-speed-inserts-with-mysql.md

* Update high-speed-inserts-with-mysql.md

* 组合软件:书 (#6832)

* Update composing-software-the-book.md

* Update composing-software-the-book.md

* Create 6-best-javascript-frameworks-in-2020.md (#6861)

* Create 6-best-javascript-frameworks-in-2020.md

* Update 6-best-javascript-frameworks-in-2020.md

* Update 6-best-javascript-frameworks-in-2020.md

* 2020 年用各大前端框架构建的 RealWorld 应用对比 (#6851)

* translation complete

* Update a-realworld-comparison-of-front-end-frameworks-2020.md

按照建议修改完成

* Update a-realworld-comparison-of-front-end-frameworks-2020.md

又修改了下破折号的格式

* Update a-realworld-comparison-of-front-end-frameworks-2020.md

修改了二级标题的显示问题

* Update a-realworld-comparison-of-front-end-frameworks-2020.md

添加相关个人信息

* Update a-realworld-comparison-of-front-end-frameworks-2020.md

Co-authored-by: lsvih <lsvih@qq.com>

* Create the-importance-of-why-docs.md (#6868)

* Create the-importance-of-why-docs.md

* Update the-importance-of-why-docs.md

* 不变性之道 (#6857)

* Update the-dao-of-immutability.md

* Update the-dao-of-immutability.md

* Update the-dao-of-immutability.md

* Update the-dao-of-immutability.md

* Update the-dao-of-immutability.md

* Update the-dao-of-immutability.md

Co-authored-by: lsvih <lsvih@qq.com>

* Create polymorphic-react-components.md (#6870)

* Create polymorphic-react-components.md

* Update polymorphic-react-components.md

* Update polymorphic-react-components.md

* Update polymorphic-react-components.md

* Create active-learning-in-machine-learning.md (#6872)

* Create kafka-vs-rabbitmq-why-use-kafka.md (#6874)

* Create kafka-vs-rabbitmq-why-use-kafka.md

* Update kafka-vs-rabbitmq-why-use-kafka.md

* Create i-built-an-app-that-uses-all-7-new-features-in-javascript-es2020.md (#6876)

* Create i-built-an-app-that-uses-all-7-new-features-in-javascript-es2020.md

* Update i-built-an-app-that-uses-all-7-new-features-in-javascript-es2020.md

* Update i-built-an-app-that-uses-all-7-new-features-in-javascript-es2020.md

* Update i-built-an-app-that-uses-all-7-new-features-in-javascript-es2020.md

* 云服务如何帮助你提高业务效率? (#6859)

* Update how-can-cloud-services-help-improve-your-businessess-efficiency.md

* Update how-can-cloud-services-help-improve-your-businessess-efficiency.md: revise according to proofreading suggestions

* Update how-can-cloud-services-help-improve-your-businessess-efficiency.md: revise according to Yinjias proofreading suggestions

* NestJS 实现基本用户认证和会话 (#6731)

* NestJS 实现基本用户认证和会话

NestJS 实现基本用户认证和会话

* fix:修改 NestJS 实现基本用户认证和会话

根据校对者意见,修改 NestJS 实现基本用户认证和会话

* Update nestjs-basic-auth-and-sessions.md

Co-authored-by: lsvih <lsvih@qq.com>

* 作为 2020 年的开发者,你应该学习 VIM 吗? (#6856)

* 更新测试

* Revert "更新测试"

This reverts commit afb007d.

* 作为2020年的开发者,你应该学习 VIM 吗?

* 校对更新

* 第二次校对修改

* 第三次校对修改

* Update TODO1/should-you-learn-vim-as-a-developer-in-2020.md

数字格式调整

Co-Authored-By: lsvih <lsvih@qq.com>

* Update TODO1/should-you-learn-vim-as-a-developer-in-2020.md

标题数字格式调整

Co-Authored-By: lsvih <lsvih@qq.com>

* 增加校对者名单

* 调整行数

* Update should-you-learn-vim-as-a-developer-in-2020.md

Co-authored-by: lsvih <lsvih@qq.com>

* MySQL 最佳实践—— 高效插入数据 (#6863)

* Finish translation

* Addressed comments

* 添加校对者信息

* Remove content with english

* Create combine-getting-started.md (#6883)

* Create combine-getting-started.md

* Update combine-getting-started.md

* Update combine-getting-started.md

* Create how-to-be-a-good-remote-developer.md (#6885)

* Create why-is-object-immutability-important.md (#6887)

* Create why-is-object-immutability-important.md

* Update why-is-object-immutability-important.md

* Create what-on-earth-is-the-shadow-dom-and-why-it-matters.md

* 2020 年排名前 6 位的 JavaScript 框架 (#6867)

* Update 6-best-javascript-frameworks-in-2020.md: Complete translation

* Update 6-best-javascript-frameworks-in-2020.md: revise according to 钱俊颖s and niayyys proofreading suggestions

* Update 6-best-javascript-frameworks-in-2020.md: add proofreaders' information

* JavaScript 风格元素 (#6878)

* JavaScript 风格元素

JavaScript 风格元素

* 翻译修改

* 修改标点符号

* 增加校对者信息

Co-authored-by: lsvih <lsvih@qq.com>

* 怎样让依赖库保持安全和最新 (#6864)

* 更新测试

* Revert "更新测试"

This reverts commit afb007d.

* 怎样让依赖库保持安全和最新

* 第一次校对提交(part)

* Create 5-best-practices-to-prevent-git-leaks.md (#6894)

* Create 5-best-practices-to-prevent-git-leaks.md

* Update 5-best-practices-to-prevent-git-leaks.md

* Create swiftui-3d-scroll-effect.md (#6896)

* Create swiftui-3d-scroll-effect.md

* Update swiftui-3d-scroll-effect.md

* Web 应用程序中的数据和 UI 分离 (#6794)

* Update separation-of-data-and-ui-in-your-web-app.md

* Update separation-of-data-and-ui-in-your-web-app.md

* fix:typo (#6903)

* 初译完成

* Update TODO1/custom-encoding-and-decoding-json-in-swift.md

Co-Authored-By: lsvih <lsvih@qq.com>

* Update TODO1/custom-encoding-and-decoding-json-in-swift.md

Co-Authored-By: lsvih <lsvih@qq.com>

* Update TODO1/custom-encoding-and-decoding-json-in-swift.md

Co-Authored-By: lsvih <lsvih@qq.com>

* Update TODO1/custom-encoding-and-decoding-json-in-swift.md

Co-Authored-By: lsvih <lsvih@qq.com>

* Update TODO1/custom-encoding-and-decoding-json-in-swift.md

Co-Authored-By: lsvih <lsvih@qq.com>

* Update TODO1/custom-encoding-and-decoding-json-in-swift.md

Co-Authored-By: lsvih <lsvih@qq.com>

* Update TODO1/custom-encoding-and-decoding-json-in-swift.md

Co-Authored-By: lsvih <lsvih@qq.com>

* Update TODO1/custom-encoding-and-decoding-json-in-swift.md

Co-Authored-By: lsvih <lsvih@qq.com>

* Update TODO1/custom-encoding-and-decoding-json-in-swift.md

Co-Authored-By: lsvih <lsvih@qq.com>

* Update TODO1/custom-encoding-and-decoding-json-in-swift.md

Co-Authored-By: lsvih <lsvih@qq.com>

* Update TODO1/custom-encoding-and-decoding-json-in-swift.md

Co-Authored-By: lsvih <lsvih@qq.com>

* Update TODO1/custom-encoding-and-decoding-json-in-swift.md

Co-Authored-By: lsvih <lsvih@qq.com>

* Update TODO1/custom-encoding-and-decoding-json-in-swift.md

Co-Authored-By: lsvih <lsvih@qq.com>

* Update TODO1/custom-encoding-and-decoding-json-in-swift.md

Co-Authored-By: lsvih <lsvih@qq.com>

* Update TODO1/custom-encoding-and-decoding-json-in-swift.md

Co-Authored-By: lsvih <lsvih@qq.com>

* Update TODO1/custom-encoding-and-decoding-json-in-swift.md

Co-Authored-By: lsvih <lsvih@qq.com>

* Update TODO1/custom-encoding-and-decoding-json-in-swift.md

Co-Authored-By: lsvih <lsvih@qq.com>

* 增加校对者信息

Co-authored-by: Amberlin1970 <37952468+Amberlin1970@users.noreply.github.com>
Co-authored-by: sun <776766759@qq.com>
Co-authored-by: Charlo <49369951+Charlo-O@users.noreply.github.com>
Co-authored-by: TiaossuP <tiaossup@yeah.net>
Co-authored-by: 小添 <xiaotian@qunhemail.com>
Co-authored-by: niayyy <yy761706@gmail.com>
Co-authored-by: lsvih <lsvih@qq.com>
Co-authored-by: zoomdong <1344492820@qq.com>
Co-authored-by: 江不知 <448300947@qq.com>
Co-authored-by: 司徒公子 <todaycoder001@gmail.com>
Co-authored-by: jianhang <snowy.yu@foxmail.com>
Co-authored-by: Roc <qinrocdev@gmail.com>
Co-authored-by: Jessica <29631279+cyz980908@users.noreply.github.com>
Co-authored-by: Amy <46389309+febrainqu@users.noreply.github.com>
  • Loading branch information
15 people authored Apr 30, 2020
1 parent 38e2cd2 commit 44cd15f
Showing 1 changed file with 73 additions and 73 deletions.
146 changes: 73 additions & 73 deletions TODO1/custom-encoding-and-decoding-json-in-swift.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,33 @@
> * 原文作者:[Leandro Fournier](https://medium.com/@lean4nier)
> * 译文出自:[掘金翻译计划](https://github.com/xitu/gold-miner)
> * 本文永久链接:[https://github.com/xitu/gold-miner/blob/master/TODO1/custom-encoding-and-decoding-json-in-swift.md](https://github.com/xitu/gold-miner/blob/master/TODO1/custom-encoding-and-decoding-json-in-swift.md)
> * 译者:
> * 校对者:
> * 译者:[chaingangway](https://github.com/chaingangway)
> * 校对者:[lsvih](https://github.com/lsvih)
# Custom encoding and decoding JSON in Swift
# 在 Swift 中对 JSON 进行自定义编码和解码的小技巧

![](https://cdn-images-1.medium.com/max/2000/0*-t2P3atrbgHMKR6P.jpg)

> This post was originally written by me at [Swift Delivery](https://www.leandrofournier.com/custom-encoding-and-decoding-json/).
本文我最早发表在 [Swift Delivery](https://www.leandrofournier.com/custom-encoding-and-decoding-json/)

In our last [Working with JSON in Swift series](https://levelup.gitconnected.com/working-with-json-in-swift-c5faea0b19a1), we explore various items:
在最近的 [Working with JSON in Swift series](https://levelup.gitconnected.com/working-with-json-in-swift-c5faea0b19a1) 文章中,我们学习了这些知识点:

* `Codable` protocol, which contains two other protocols: `Encodable` and `Decodable`
* How to decode a JSON data object into a readable Swift struct
* Usage of custom keys
* Custom objects creation
* Arrays
* Different top level entities
* `Codable` 协议,它还包含另外两个协议: `Encodable` `Decodable`
* 如何将 JSON 数据对象解析成具有可读性的 Swift 结构体。
* 自定义 key 的使用。
* 自定义对象的创建。
* 数组
* 各种一级实体

That’s enough for a basic usage of JSON in Swift, which will enable us to read JSON data (decode) and create a new object which can be converted back to JSON (encode) and send it, for instance, to a RESTFul API.
通过了解这些,你能掌握 Swift 中 JSON 的基本使用。比如,你可以读取 JSON 数据(解码),创建可以被转换为 JSON 格式的对象(编码),然后把这个对象发送给 RestFul API

So, first things first: let’s create an object and convert it to a JSON data format.
首先,我们来创建一个对象,把它转换成 JSON 数据格式。

## Encoding
## 编码

#### Default encoding
#### 默认编码

Let’s assume we have the following `struct` for insects:
下面的代码中定义了 Insect 结构体:

```swift
struct Insect: Codable {
Expand All @@ -44,22 +44,22 @@ struct Insect: Codable {
}
```

To sum up, we have three properties. **insectId** for the insect identifier, **name** for its name and **isHelpful** to specify if the insect is helpful or not to our garden. Two of these properties use custom keys (**insectId** and **isHelpful**).
结构体中一共有三个属性。**insectId** 表示昆虫的身份,**name** 表示昆虫的名称,**isHelpful** 表示昆虫是否对我们的花园有益。其中两个属性使用了自定义 key(**insectId** **isHelpful**)。

Now let’s create an insect:
现在我们新建一个昆虫实例:

```swift
let newInsect = Insect(insectId: 1006, name: "ants", isHelpful: true)
```

Our RESTful API expects to receive a JSON with this new insect information. Then we have to encode it:
我们的 RESTFul API 需要接收 JSON 格式的昆虫数据,所以我们需要对它进行编码:

```swift
let encoder = JSONEncoder()
let insectData: Data? = try? encoder.encode(newInsect)
```

That was easy: now **insectData** is an object of type `Data?`. We might want to check whether the encoding actually worked (just a check, you probably won't do this in your code). Let's rewrite the code above and use some optional unwrapping:
这一步很简单:现在 **insectData** 已经是 `Data?` 类型。我们可能还想检查一下编码是否真的生效了(只是一个验证,你在写代码时可以不必这样)。我们用解包的方式来重构上面的代码:

```swift
let encoder = JSONEncoder()
Expand All @@ -70,21 +70,21 @@ if let insectData = try? encoder.encode(newInsect),
}
```

1. Create the encoder
2. Try to encode the object we’ve created
3. Convert, if possible, the `Data` object into a `String`
1. 创建 encoder
2. 尝试对我们创建的对象编码。
3. 进行转换,如果编码成功的话,`Data` 对象会变成 `String` 类型。

Then we print out the result which will look like this:
我们打印一下结果,它的格式如下:

```json
{"name":"ants","is_helpful":true,"insect_id":1006}
```

> Note that the keys used while encoding are not the custom keys (**insectId** and **isHelpful**) but the expected keys (**insect_id** and **is_helpful**). Nice!
> 注意编码时的 key 不是自定义的 key(**insectId** **isHelpful**),而是我们希望的 key(**insect_id** **is_helpful**)。太棒了!
#### Custom encoding
#### 自定义编码

Let’s suppose our RESTful API expects to receive the name of the insect uppercased. We need to create our own implementation of the encoding method so to make sure the name of the insect is sent uppercased. We must implement the method **func** encode(to encoder: Encoder) **throws** of the `Encodable` protocol inside our **Insect** `struct`.
假设 RESTful API 需要接受大写名称的昆虫数据。我们就需要实现自己的编码方法,来保证昆虫名称是大写的。要这样做的话,我们就必须在 **Insect** 结构体中实现 `Encodable` 协议中的 **func** encode(to encoder: Encoder) **throws** 方法。

```swift
struct Insect: Codable {
Expand All @@ -99,31 +99,31 @@ struct Insect: Codable {
}

func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(insectId, forKey: .insectId)
try container.encode(name.uppercased(), forKey: .name)
try container.encode(isHelpful, forKey: .isHelpful)
var container = encoder.container(keyedBy: CodingKeys.self) // 13
try container.encode(insectId, forKey: .insectId) // 14
try container.encode(name.uppercased(), forKey: .name) // 15
try container.encode(isHelpful, forKey: .isHelpful) // 16
}
}
```

Line 13 is where we create a container where encoded values will be stored. The container MUST be a `var` because it's mutable and MUST receive the keys to be used.
13 行我们创建了一个用于存储编码数据的容器。这个容器必须是 `var` 类型,它要接收这些 key,因此是可变类型的。

Lines 14 to 16 are used to encode the values into the container, which is done using `try` because any of these can throw an error.
14 16 行是把数据进行编码后,存储到容器中。每一次存储都可能抛出异常,所以这里用到了 `try`

Now, look at line 15: we don’t just put the value as it is but we uppercase it, which is main reason we’re implementing a custom encoding.
现在,看第 15 行:我们没有原封不动地把数据存储,而是对其进行了大写处理。这就是我们要实现自定义编码的主要原因。

If you run the code above, where we create the **Insect** “ants”, we’ll see that after encoding and converting the resulting JSON `Data` into a `String` we get the following:
运行上面的代码后,你会发现 **Insect** 中的“ants”属性在编码转换成 JSON 字符串后,格式是下面这样的:

```
{"name":"ANTS","is_helpful":true,"insect_id":1006}
```

As you might have seen, the name of the insect is now uppercased despite we’ve created it lowercased. How cool is that!
即使昆虫名称的初始值是小写的,现在它的名称也变成了大写。这太酷了!

## Custom decoding
## 自定义解码

So far we’ve been relying on the default decoding method of the `Decodable` protocol. But let's take a look at another scenario.
目前为止,我们一直都依赖 `Decodable` 协议中默认的解码方法。下面我们来看看另外的方法:

```json
[
Expand Down Expand Up @@ -172,70 +172,70 @@ So far we’ve been relying on the default decoding method of the `Decodable` pr
]
```

The API is retrieving the **is_helpful** property inside a **details** entity. But we don’t want to create a **Details** object: we just want to flatten that object so we can use our existing **Insect** object.
API 获取的 **is_helpful** 属性在 **details** 实体内部。但是我们不想创建 **Details** 对象,我们只想展开它,这样就可以直接用现有的 **Insect** 对象了。

Time to use our own implementation of the **init**(from decoder: Decoder) **throws** method of the `Decodable` protocol and some extra work. Let's get started.
现在我们要实现 `Decodable` 协议中的 **init**(from decoder: Decoder) **throws** 方法,然后做一些额外处理。

First of all, coding keys has changed because **is_helpful** is not a key in the same level as before AND there’s a new one called **details**. To fix that:
首先,key 不一样了,**is_helpful** 不是同级的 key了,这里新的 key **details**。我们这样编写代码:

```swift
enum CodingKeys: String, CodingKey {
case insectId = "insect_id"
case name
case details
case details // 4
}

enum DetailsCodingKeys: String, CodingKey {
case isHelpful = "is_helpful"
}
enum DetailsCodingKeys: String, CodingKey { // 7
case isHelpful = "is_helpful" // 8
} // 9
```

In line 4 we replace the existing key with the new one, **details**.
第 4 行,我们用 **details** 替换了之前的 key。

In lines 7 and 9 we create a new set of keys, the ones that exist inside **details**, which in this case is just one, **isHelpful**.
第 7 行到第 9 行,我们新建了一个枚举,对应 **details** 内部的 key,在本例中,只有一个 **isHelpful**

> Note that we didn’t touch the properties of the **Insect** `struct`.
> 注意我们还没有接触到 **Insect** `结构体`的属性。
Now let’s dive into the decoder initialization:
下面我们深入了解一下解码的初始化方法:

```swift
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let container = try decoder.container(keyedBy: CodingKeys.self) // 2

insectId = try container.decode(Int.self, forKey: .insectId)
name = try container.decode(String.self, forKey: .name)
let details = try container.nestedContainer(keyedBy: DetailsCodingKeys.self, forKey: .details)
isHelpful = try details.decode(Bool.self, forKey: .isHelpful)
insectId = try container.decode(Int.self, forKey: .insectId) // 4
name = try container.decode(String.self, forKey: .name) // 5
let details = try container.nestedContainer(keyedBy: DetailsCodingKeys.self, forKey: .details) // 6
isHelpful = try details.decode(Bool.self, forKey: .isHelpful) // 7
}
```

In line 2 we create the container which decodes the whole JSON structure.
第 2 行中我们创建了用于解析整个 JSON 结构的容器。

In line 4 and 5 we just decode the `Int` value for the **insectId** property and the `String` value for the **name** property.
第 4 行和第 5 行,我们解析了 **insectId** 属性的 `Int` 数据和 **name** 属性的 `String` 数据。

In line 6 we grab the nested container under the **details** key which is keyed by the brand new **DetailsCodingKeys** `enum`.
第 6 行,我们获得了 **details** key 内部的容器,容器内的 key 是通过 **DetailsCodingKeys** `枚举`创建的。

In line 7 we just decode the `Bool` value for the **isHelpful** property inside our new **details** container.
第 7 行,我们在 **details** 的容器中解析了 **isHelpful** 属性的 `Bool` 数据。

BUT that’s not it. Since our **CodingKeys** has changed by adding the **details** case, our custom encoding implementation must be fixed. So let’s do that:
但是事情还没有做完。我们在 **CodingKeys** 中加入了 **details**,所以我们自定义的编码方法也要如下修改:

```swift
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(insectId, forKey: .insectId)
try container.encode(name.uppercased(), forKey: .name)
var details = container.nestedContainer(keyedBy: DetailsCodingKeys.self, forKey: .details)
try details.encode(isHelpful, forKey: .isHelpful)
var details = container.nestedContainer(keyedBy: DetailsCodingKeys.self, forKey: .details) // 5
try details.encode(isHelpful, forKey: .isHelpful) // 6
}
```

We just changed the way we encode the **isHelpful** property.

In line 5 we create a new nested container, using the keys inside the **DetailsCodingKeys** `enum` and to be used inside the **details** entity inside our JSON.
我们只用修改 **isHelpful** 属性的编码方式就可以了。
在第 5 行中我们用 **DetailsCodingKeys** `枚举`作为 key 创建了一个内部容器,用于在 **details** 实体的内部使用。

In line 6 we encode **isHelpful** INSIDE the brand new **details** nested container.
第 6 行我们在新建的 **details** 内部容器中对 **isHelpful** 进行编码。

So, to sum up, our **Insect** `struct` looks like this:
所以,最终的 **Insect** `结构体`是这样的:

```swift
struct Insect: Codable {
Expand Down Expand Up @@ -273,7 +273,7 @@ struct Insect: Codable {
}
```

If we decode it:
下面开始解码:

```swift
let decoder = JSONDecoder()
Expand All @@ -282,21 +282,21 @@ if let insects = try? decoder.decode([Insect].self, from: jsonData!) {
}
```

We’ll get something like this:
我们会得到下面的结果:

```
[__lldb_expr_54.Insect(insectId: 1001, name: "BEES", isHelpful: true), __lldb_expr_54.Insect(insectId: 1002, name: "LADYBUGS", isHelpful: true), __lldb_expr_54.Insect(insectId: 1003, name: "SPIDERS", isHelpful: true), __lldb_expr_54.Insect(insectId: 2001, name: "TOMATO HORN WORMS", isHelpful: false), __lldb_expr_54.Insect(insectId: 2002, name: "CABBAGE WORMS", isHelpful: false), __lldb_expr_54.Insect(insectId: 2003, name: "CABBAGE MOTHS", isHelpful: false)]
```

As you can see, there’s no **details** entity: just our `struct` properties.
你可以看到,并没有 **details** 实体,只有 `结构体` 的属性。

The encoding will work as expected as well.
编码流程也是正常的。

This post, plus the previous series, sums up pretty much the most common scenarios you may run into when working with JSON in Swift.
本文和之前的一系列文章,总结了很多在 Swift 中处理 JSON 最常见的场景。

## Need more information?
## 更多内容

Ben Scheirman’s [Ultimate Guide to JSON Parsing with Swift](https://benscheirman.com/2017/06/swift-json/) is the most useful source I could find for this subject.
推荐 Ben Scheirman 写的 [Ultimate Guide to JSON Parsing with Swift](https://benscheirman.com/2017/06/swift-json/) 这篇文章,它是与本文主题相关最实用的资料。

> 如果发现译文存在错误或其他需要改进的地方,欢迎到 [掘金翻译计划](https://github.com/xitu/gold-miner) 对译文进行修改并 PR,也可获得相应奖励积分。文章开头的 **本文永久链接** 即为本文在 GitHub 上的 MarkDown 链接。
Expand Down

0 comments on commit 44cd15f

Please sign in to comment.