JSON 응답의 구조와 코드에 있는 구조체의 불일치를 해결하기 위해서는 구조체 이름을 유지하면서, 일부 이름을 수정하고 적절한 타입 매핑을 수행해야 합니다.
실제 외부 API를 통해 받아온 데이터 모델
{
"response": {
"header": {
"resultCode": "0000",
"resultMsg": "OK"
},
"body": {
"items": {
"item": [
{
"contentid": "1095732",
"originimgurl": "http://tong.visitkorea.or.kr/cms/resource/67/3035567_image2_1.png",
"imgname": "서울빛초롱축제 포스터",
"smallimageurl": "http://tong.visitkorea.or.kr/cms/resource/67/3035567_image3_1.png",
"cpyrhtDivCd": "Type3",
"serialnum": "3035567_3"
},
{
"contentid": "1095732",
"originimgurl": "http://tong.visitkorea.or.kr/cms/resource/68/3035568_image2_1.jpg",
"imgname": "서울빛초롱축제 1",
"smallimageurl": "http://tong.visitkorea.or.kr/cms/resource/68/3035568_image3_1.jpg",
"cpyrhtDivCd": "Type3",
"serialnum": "3035568_2"
},
...
]
},
"numOfRows": 10,
"pageNo": 1,
"totalCount": 11
}
}
}
⭐️ 위에 나온 대로 데이터 모델을 작성하면 되지만, 이거 말고 다른 데이터 모델을 사용하고 있으면서 이전의 이름이 공통으로 사용되는 부분이 있어서 이름을 좀 바꿔야 했습니다.
수정된 데이터 모델
import Foundation
// 최상위 응답 구조체
struct ImageResponseResponse: Codable {
let response: ImageResponse
}
// 응답의 상위 구조체
struct ImageResponse: Codable {
let header: ImageHeader
let body: ImageBody
}
// 헤더 정보
struct ImageHeader: Codable {
let resultCode: String
let resultMsg: String
}
// 바디 구조체 (실제 데이터가 포함되는 부분)
struct ImageBody: Codable {
let items: ImageItems
let numOfRows: Int
let pageNo: Int
let totalCount: Int
}
// 아이템들을 포함하는 구조체
struct ImageItems: Codable {
let item: [ImageItem]
}
// 각각의 이미지 정보를 포함하는 구조체
struct ImageItem: Codable {
let contentid: String
let originimgurl: String
let imgname: String
let smallimageurl: String
let cpyrhtDivCd: String
let serialnum: String
}
// CodingKeys를 사용하여 JSON의 키와 프로퍼티를 매핑
extension ImageResponseResponse {
enum CodingKeys: String, CodingKey {
case response
}
}
extension ImageResponse {
enum CodingKeys: String, CodingKey {
case header
case body
}
}
extension ImageHeader {
enum CodingKeys: String, CodingKey {
case resultCode
case resultMsg
}
}
extension ImageBody {
enum CodingKeys: String, CodingKey {
case items
case numOfRows
case pageNo
case totalCount
}
}
extension ImageItems {
enum CodingKeys: String, CodingKey {
case item
}
}
⭐️ ImageItem 구조체에 대해 CodingKeys를 따로 정의할 필요는 없습니다. 이유는 ImageItem에 포함된 프로퍼티 이름들이 JSON의 키 이름과 정확히 일치하기 때문입니다. Swift의 Codable 프로토콜은 기본적으로 프로퍼티 이름과 JSON 키가 동일한 경우 자동으로 매핑을 해줍니다.
🔥 CodingKeys가 필요한 경우 🔥
CodingKeys는 JSON의 키와 구조체의 프로퍼티 이름이 다를 때 사용됩니다. 예를 들어, 만약 JSON에서 contentid라는 키가 content_id로 되어 있으면, CodingKeys를 사용하여 다음과 같이 매핑할 수 있습니다.
struct ImageItem: Codable {
let contentid: String
let originimgurl: String
let imgname: String
let smallimageurl: String
let cpyrhtDivCd: String
let serialnum: String
enum CodingKeys: String, CodingKey {
case contentid = "content_id"
case originimgurl = "origin_image_url"
case imgname = "image_name"
case smallimageurl = "small_image_url"
case cpyrhtDivCd = "copyright_code"
case serialnum = "serial_number"
}
}
1. CodingKeys를 구조체 내부에 정의하는 방법
가장 흔히 사용되는 방식으로, 구조체 내부에 CodingKeys를 정의하는 것입니다. 이 방식은 CodingKeys가 구조체의 일부임을 명확하게 보여줍니다.
struct ImageItem: Codable {
let contentid: String
let originimgurl: String
let imgname: String
let smallimageurl: String
let cpyrhtDivCd: String
let serialnum: String
enum CodingKeys: String, CodingKey {
case contentid
case originimgurl
case imgname
case smallimageurl
case cpyrhtDivCd
case serialnum
}
}
2. extension을 사용해서 CodingKeys를 정의하는 방법
당신이 보낸 것처럼 extension을 사용하면, 구조체 본체와 CodingKeys 정의를 분리할 수 있습니다. 이는 코드의 가독성을 높이거나, 확장성 있는 구조로 관리하려고 할 때 유용할 수 있습니다.
struct ImageItem: Codable {
let contentid: String
let originimgurl: String
let imgname: String
let smallimageurl: String
let cpyrhtDivCd: String
let serialnum: String
}
extension ImageItem {
enum CodingKeys: String, CodingKey {
case contentid
case originimgurl
case imgname
case smallimageurl
case cpyrhtDivCd
case serialnum
}
}
두 방법의 차이
- 구조적 차이:
- extension을 사용하면 구조체 자체와 CodingKeys 정의를 분리해서 관리할 수 있어, 특히 복잡한 구조체나 여러 가지 확장 기능이 있을 때 도움이 됩니다.
- 구조체 내부에 정의하면 모든 관련 코드가 한 곳에 있어서, 한눈에 구조체의 설계와 CodingKeys가 어떻게 매핑되는지 파악할 수 있습니다.
- 유연성:
- extension을 사용하면 나중에 구조체를 확장하거나, 추가적인 기능을 모듈화하고 분리된 파일에 정의하는 것이 더 쉽습니다.
- 스타일:
- 둘 중 어느 방식이 더 좋은지는 팀의 코드 스타일에 따라 다릅니다. 일반적으로 작은 구조체에서는 내부에 CodingKeys를 정의하고, 코드가 길어지거나 관리해야 할 것이 많을 때는 extension을 사용하기도 합니다.
결론
- 기능적인 차이는 없습니다. 둘 다 CodingKeys를 제공하는 방식일 뿐입니다.
- extension은 구조를 분리해서 좀 더 모듈화된 코드를 만들 수 있게 해줍니다.
'Swift' 카테고리의 다른 글
heightAnchor랑 bottomAnchor는 뭐가 다를까? (0) | 2024.09.06 |
---|---|
외부 API를 받는 데이터 함수의 데이터 타입 관리 (0) | 2024.09.06 |
enum을 통해 api 함수 관리해보기 (0) | 2024.08.31 |
헷갈리기 쉬운 델리게이트 패턴으로 컬렉션 셀의 데이터 전달하기 (0) | 2024.08.28 |
콜백 함수는 언제 쓰이나요? (0) | 2024.08.23 |