영진위 api json


{
  "boxOfficeResult": {
    "boxofficeType": "일별 박스오피스",
    "showRange": "20240501~20240501",
    "dailyBoxOfficeList": [
      {
        "rnum": "1",
        "rank": "1",
        "rankInten": "0",
        "rankOldAndNew": "OLD",
        "movieCd": "20228797",
        "movieNm": "범죄도시4",
        "openDt": "2024-04-24",
        "salesAmt": "7173755964",
        "salesShare": "84.8",
        "salesInten": "3490937394",
        "salesChange": "94.8",
        "salesAcc": "54743912218",
        "audiCnt": "784809",
        "audiInten": "394859",
        "audiChange": "101.3",
        "audiAcc": "5790321",
        "scrnCnt": "2702",
        "showCnt": "14172"
      },
      {
        "rnum": "2",
        "rank": "2",
        "rankInten": "0",
        "rankOldAndNew": "OLD",
        "movieCd": "20236614",
        "movieNm": "쿵푸팬더4",
        "openDt": "2024-04-10",
        "salesAmt": "336923219",
        "salesShare": "4.0",
        "salesInten": "243213158",
        "salesChange": "259.5",
        "salesAcc": "13462011584",
        "audiCnt": "38600",
        "audiInten": "28087",
        "audiChange": "267.2",
        "audiAcc": "1443199",
        "scrnCnt": "600",
        "showCnt": "919"
      },
      {
        "rnum": "3",
        "rank": "3",
        "rankInten": "0",
        "rankOldAndNew": "NEW",
        "movieCd": "20235613",
        "movieNm": "스턴트맨",
        "openDt": "2024-05-01",
        "salesAmt": "357447723",
        "salesShare": "4.2",
        "salesInten": "357447723",
        "salesChange": "100",
        "salesAcc": "660244723",
        "audiCnt": "35374",
        "audiInten": "35374",
        "audiChange": "100",
        "audiAcc": "68479",
        "scrnCnt": "801",
        "showCnt": "2244"
      },
      {
        "rnum": "4",
        "rank": "4",
        "rankInten": "0",
        "rankOldAndNew": "NEW",
        "movieCd": "20249313",
        "movieNm": "포켓몬스터: 성도지방 이야기, 최종장",
        "openDt": "2024-05-01",
        "salesAmt": "278724769",
        "salesShare": "3.3",
        "salesInten": "278724769",
        "salesChange": "100",
        "salesAcc": "280484769",
        "audiCnt": "32927",
        "audiInten": "32927",
        "audiChange": "100",
        "audiAcc": "33087",
        "scrnCnt": "658",
        "showCnt": "1446"
      },
      {
        "rnum": "5",
        "rank": "5",
        "rankInten": "0",
        "rankOldAndNew": "OLD",
        "movieCd": "20231677",
        "movieNm": "남은 인생 10년",
        "openDt": "2023-05-24",
        "salesAmt": "51708205",
        "salesShare": "0.6",
        "salesInten": "7596913",
        "salesChange": "17.2",
        "salesAcc": "4382668970",
        "audiCnt": "5326",
        "audiInten": "812",
        "audiChange": "18",
        "audiAcc": "430512",
        "scrnCnt": "108",
        "showCnt": "142"
      },
      {
        "rnum": "6",
        "rank": "6",
        "rankInten": "-3",
        "rankOldAndNew": "OLD",
        "movieCd": "20234675",
        "movieNm": "파묘",
        "openDt": "2024-02-22",
        "salesAmt": "39390826",
        "salesShare": "0.5",
        "salesInten": "-29943572",
        "salesChange": "-43.2",
        "salesAcc": "114670144872",
        "audiCnt": "4251",
        "audiInten": "-3157",
        "audiChange": "-42.6",
        "audiAcc": "11864316",
        "scrnCnt": "141",
        "showCnt": "183"
      },
      {
        "rnum": "7",
        "rank": "7",
        "rankInten": "0",
        "rankOldAndNew": "NEW",
        "movieCd": "20249133",
        "movieNm": "극장판 실바니안 패밀리: 프레야의 선물",
        "openDt": "2024-05-01",
        "salesAmt": "29828450",
        "salesShare": "0.4",
        "salesInten": "29828450",
        "salesChange": "100",
        "salesAcc": "34224450",
        "audiCnt": "3948",
        "audiInten": "3948",
        "audiChange": "100",
        "audiAcc": "4576",
        "scrnCnt": "188",
        "showCnt": "280"
      },
      {
        "rnum": "8",
        "rank": "8",
        "rankInten": "0",
        "rankOldAndNew": "NEW",
        "movieCd": "20249353",
        "movieNm": "꼬마참새 리차드: 신비한 보석 탐험대",
        "openDt": "2024-05-01",
        "salesAmt": "29553100",
        "salesShare": "0.3",
        "salesInten": "29553100",
        "salesChange": "100",
        "salesAcc": "43045400",
        "audiCnt": "3851",
        "audiInten": "3851",
        "audiChange": "100",
        "audiAcc": "5305",
        "scrnCnt": "154",
        "showCnt": "205"
      },
      {
        "rnum": "9",
        "rank": "9",
        "rankInten": "-5",
        "rankOldAndNew": "OLD",
        "movieCd": "20249318",
        "movieNm": "챌린저스",
        "openDt": "2024-04-24",
        "salesAmt": "35507320",
        "salesShare": "0.4",
        "salesInten": "-21340719",
        "salesChange": "-37.5",
        "salesAcc": "369939305",
        "audiCnt": "3612",
        "audiInten": "-2457",
        "audiChange": "-40.5",
        "audiAcc": "39067",
        "scrnCnt": "129",
        "showCnt": "152"
      },
      {
        "rnum": "10",
        "rank": "10",
        "rankInten": "-4",
        "rankOldAndNew": "OLD",
        "movieCd": "20248466",
        "movieNm": "고스트버스터즈: 오싹한 뉴욕",
        "openDt": "2024-04-17",
        "salesAmt": "16081700",
        "salesShare": "0.2",
        "salesInten": "7039244",
        "salesChange": "77.8",
        "salesAcc": "416480161",
        "audiCnt": "2021",
        "audiInten": "866",
        "audiChange": "75",
        "audiAcc": "44852",
        "scrnCnt": "50",
        "showCnt": "51"
      }
    ]
  }
}

Tree, Code 형식으로 보기 (Code Beautify)

Tree image

Code image

JSON 데이터 모델 만들기

app.quicktype.io 이용

// This file was generated from JSON Schema using quicktype, do not modify it directly.
// To parse the JSON, add this file to your project and do:
//
//   let welcome = try? JSONDecoder().decode(Welcome.self, from: jsonData)

import Foundation

// MARK: - Welcome
struct Welcome: Codable {
    let boxOfficeResult: BoxOfficeResult
}

// MARK: - BoxOfficeResult
struct BoxOfficeResult: Codable {
    let boxofficeType, showRange: String
    let dailyBoxOfficeList: [DailyBoxOfficeList]
}

// MARK: - DailyBoxOfficeList
struct DailyBoxOfficeList: Codable {
    let rnum, rank, rankInten: String
    let rankOldAndNew: RankOldAndNew
    let movieCD, movieNm, openDt, salesAmt: String
    let salesShare, salesInten, salesChange, salesAcc: String
    let audiCnt, audiInten, audiChange, audiAcc: String
    let scrnCnt, showCnt: String

    enum CodingKeys: String, CodingKey {
        case rnum, rank, rankInten, rankOldAndNew
        case movieCD = "movieCd"
        case movieNm, openDt, salesAmt, salesShare, salesInten, salesChange, salesAcc, audiCnt, audiInten, audiChange, audiAcc, scrnCnt, showCnt
    }
}

enum RankOldAndNew: String, Codable {
    case new = "NEW"
    case old = "OLD"
}
// To parse the JSON, install Klaxon and do:
//
//   val welcome = Welcome.fromJson(jsonString)

package quicktype

import com.beust.klaxon.*

private fun <T> Klaxon.convert(k: kotlin.reflect.KClass<*>, fromJson: (JsonValue) -> T, toJson: (T) -> String, isUnion: Boolean = false) =
    this.converter(object: Converter {
        @Suppress("UNCHECKED_CAST")
        override fun toJson(value: Any)        = toJson(value as T)
        override fun fromJson(jv: JsonValue)   = fromJson(jv) as Any
        override fun canConvert(cls: Class<*>) = cls == k.java || (isUnion && cls.superclass == k.java)
    })

private val klaxon = Klaxon()
    .convert(RankOldAndNew::class, { RankOldAndNew.fromValue(it.string!!) }, { "\"${it.value}\"" })

data class Welcome (
    val boxOfficeResult: BoxOfficeResult
) {
    public fun toJson() = klaxon.toJsonString(this)

    companion object {
        public fun fromJson(json: String) = klaxon.parse<Welcome>(json)
    }
}

data class BoxOfficeResult (
    val boxofficeType: String,
    val showRange: String,
    val dailyBoxOfficeList: List<DailyBoxOfficeList>
)

data class DailyBoxOfficeList (
    val rnum: String,
    val rank: String,
    val rankInten: String,
    val rankOldAndNew: RankOldAndNew,

    @Json(name = "movieCd")
    val movieCD: String,

    val movieNm: String,
    val openDt: String,
    val salesAmt: String,
    val salesShare: String,
    val salesInten: String,
    val salesChange: String,
    val salesAcc: String,
    val audiCnt: String,
    val audiInten: String,
    val audiChange: String,
    val audiAcc: String,
    val scrnCnt: String,
    val showCnt: String
)

enum class RankOldAndNew(val value: String) {
    New("NEW"),
    Old("OLD");

    companion object {
        public fun fromValue(value: String): RankOldAndNew = when (value) {
            "NEW" -> New
            "OLD" -> Old
            else  -> throw IllegalArgumentException()
        }
    }
}

RESTful API


image

image

image

image

image

image

image

RESTful API를 사용하면 URI만 봐도 어떤 사이트인지 알 수 있다.

JSON


image

image

image

Open API 활용 사례

image

네이버 Open API

Open API를 이용한 앱 개발 단계

  1. 원하는 정보를 제공하는 웹 서비스와 사용할 Open API 선정
  2. Open API 사용을 위한 신청과 인증키 발급
  3. 네트워크를 통해 데이터 요청
  4. 받은 데이터를 파싱하여 앱에서 사용

MovieCMU


Constraints

image

dequeueReusableCell

image








출처


  • Smile Han의 iOS 프로그래밍 실무, 한성현(출판 예정), PPT로 제공
  • Do it! 스위프트로 아이폰 앱 만들기 입문(개정 7판)(이지스퍼블리싱,송호정, 이범근, 2023.1)
  • 핵심만 골라 배우는 SwiftUI 기반의 iOS 프로그래밍(제이펍, 닐 스미스, 2023.12)
    • https://www.techotopia.com/index.php/IOS_iPhone_iPad_eBooks
  • 스위프트 프로그래밍(Swift 5) 3판(한빛미디어, 야곰, 2019.10)
  • 꼼꼼한 재은 씨의 스위프트 기본편 (루비페이퍼, 이재은, 2018.05)
  • 꼼꼼한 재은 씨의 스위프트 실전편 (Swift) (루비페이퍼, 이재은, 2018.08)
  • 꼼꼼한 재은 씨의 Swift 문법편 (루비페이퍼, 이재은, 2017.12)