Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- UITextView
- combine
- tableView
- RxCocoa
- Refactoring
- Clean Code
- rxswift
- clean architecture
- uiscrollview
- 클린 코드
- UICollectionView
- 스위프트
- swift documentation
- 리펙터링
- SWIFT
- HIG
- map
- Protocol
- MVVM
- Xcode
- 리팩토링
- collectionview
- ios
- Observable
- 리펙토링
- ribs
- 애니메이션
- swiftUI
- Human interface guide
- uitableview
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] json, codable, nestedContainer(keyedBy:forKey:), Decoding 중첩 모델 처리 방법 (디코딩) 본문
iOS 응용 (swift)
[iOS - swift] json, codable, nestedContainer(keyedBy:forKey:), Decoding 중첩 모델 처리 방법 (디코딩)
jake-kim 2022. 2. 7. 23:49* 기본적인 Codable, Decode, Encode 개념은 이곳 참고
* 관련 포스팅 글
- json, nestedContainer(keyedBy:forKey:), Decoding 중첩 모델 처리 방법 (디코딩)
- json, nestedContainer(keyedBy:forKey:), Encoding 중첩 모델 처리 방법 (인코딩)
- json, nestedContainer(keyedBy:forKey:), KeyedCodable로 중첩 모델 처리 방법
중첩 모델을 flatten 모델로 정의 방법
- nestedContainer(keyedBy:forKey:) 사용
- nestedContainer에 접근할때 사용되는 메소드
ex) 아래 json 데이터에서 blog_info.name.first 값만 사용하고 싶은 경우, flat하게 모델 정의 방법?
{
"user_id": "jake",
"blog_info": {
"name": {
"first": "iOS 앱 개발 알아가기",
"second": "SwiftUI 앱 개발 알아가기"
}
}
}
nestedContainer 사용 x - 중첩 | nestedContainer 사용 o - flatten |
구현 방법
- 아래 blog_info.name.first를 nested하지 않고 바로 myModel.blogName으로 접근하는 방법 구현
{
"user_id": "jake",
"blog_info": {
"name": {
"first": "iOS 앱 개발 알아가기",
"second": "SwiftUI 앱 개발 알아가기"
}
}
}
- nested된 json key값들을 정의하기 위해 String, CodingKey를 준수하는 enum타입 여러개 정의
- blog_info, name 두 개의 enum이 필요
- 중첩모델에 해당되는 코드들을 String, CodingKey를 준수하는 enum타입으로 선언
struct MyModel { enum CodingKeys: String, CodingKey { case userID = "user_id" case blogInfo = "blog_info" } enum BlogInfoKeys: String, CodingKey { case name } enum NameKeys: String, CodingKey { case first case second } var userID: String? var blogName: String? }
- init(from decoder: Decoder) throws 정의
cf) Encoding 사용할 경우, Encodable을 준수하고 encode(to encoder: Encoder) throws 메소드를 정의
extension MyModel: Decodable { init(from decoder: Decoder) throws { // TODO }
- decoder 인스턴스를 통해 container coding key 획득
let codingKeys = try decoder.container(keyedBy: CodingKeys.self)
- nested 되어 있지 않은 프로퍼티는 바로 디코딩 수행
self.userID = try codingKeys.decode(String.self, forKey: .userID)
- nested 되어 있다면 nestedContainer(keyedBy:forKey:)로 접근
MyModel.blog_info 접근
let blogInfoKeys = try codingKeys.nestedContainer(keyedBy: BlogInfoKeys.self, forKey: .blogInfo)
- MyModel.blog_info.name 접근
let nameKeys = try blogInfoKeys.nestedContainer(keyedBy: NameKeys.self, forKey: .name)
- MyModel.blog_info.name.first 접근
self.blogName = try nameKeys.decode(String.self, forKey: .first)
* MyModel 전체 코드
struct MyModel {
enum CodingKeys: String, CodingKey {
case userID = "user_id"
case blogInfo = "blog_info"
}
enum BlogInfoKeys: String, CodingKey {
case name
}
enum NameKeys: String, CodingKey {
case first
case second
}
var userID: String?
var blogName: String?
}
extension MyModel: Decodable {
init(from decoder: Decoder) throws {
let codingKeys = try decoder.container(keyedBy: CodingKeys.self)
self.userID = try codingKeys.decode(String.self, forKey: .userID)
let blogInfoKeys = try codingKeys.nestedContainer(keyedBy: BlogInfoKeys.self, forKey: .blogInfo)
let nameKeys = try blogInfoKeys.nestedContainer(keyedBy: NameKeys.self, forKey: .name)
self.blogName = try nameKeys.decode(String.self, forKey: .first)
}
}
사용하는 쪽
class ViewController: UIViewController {
let jsonSample = """
{
"user_id": "jake",
"blog_info": {
"name": {
"first": "iOS 앱 개발 알아가기",
"second": "SwiftUI 앱 개발 알아가기"
}
}
}
"""
override func viewDidLoad() {
super.viewDidLoad()
guard
let data = self.jsonSample.data(using: .utf8),
let myModel = try? JSONDecoder().decode(MyModel.self, from: data)
else { return }
print(myModel.blogName) // iOS 앱 개발 알아가기
}
}
* 전체 코드: https://github.com/JK0369/ExDecoding
'iOS 응용 (swift)' 카테고리의 다른 글
Comments