新手的 Swift JSON decode 練習題

  • 搭配 AI 建立自己感興趣的 JSON API
  • iTunes
  • apple marketing tools RSS generator
  • Random User Generator
  • GitHub
  • Joke
  • REST Countries
  • Open Trivia(是非題/選擇題)
  • IG
  • Xcode Releases
  • JSONPlaceholder
  • UI Faces
  • 請 AI 提供 API 網址
  • 第三方 API 整理

題目

  • 搭配 AI 建立自己感興趣的 JSON API
  • iTunes

ex

https://itunes.apple.com/search?term=戴佩妮&media=music&country=tw
  • apple marketing tools RSS generator

ex

https://rss.applemarketingtools.com/api/v2/tw/music/most-played/10/songs.json
  • Random User Generator

ex

https://randomuser.me/api/?results=10
  • GitHub

ex

https://api.github.com/users/twostraws/followers
  • JokeAPI
  • REST Countries
  • Open Trivia API
  • IG

抓取方法可參考以下連結。

若想直接練習,可從以下網址抓取最近退休的費神 Roger Federer 的 IG 動態 JSON。

https://raw.githubusercontent.com/AppPeterPan/CutePic/main/rogerfederer.json
  • Xcode Releases
https://xcodereleases.com/data.json
  • JSONPlaceholder
  • UI Faces
  • 請 AI 提供 API 網址
  • 第三方 API 整理

解答

  • iTunes

https://itunes.apple.com/search?term=戴佩妮&media=music&country=tw

struct SearchResponse: Decodable {
let resultCount: Int
let results: [StoreItem]
}

struct StoreItem: Decodable {
let artistName: String
let trackName: String
let collectionName: String?
let previewUrl: URL
let artworkUrl100: URL
let trackPrice: Double?
let releaseDate: Date
let isStreamable: Bool?
}

解碼的 decoder。

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let searchResponse = try decoder.decode(SearchResponse.self, from: data)
  • apple marketing tools RSS generator

https://rss.applemarketingtools.com/api/v2/tw/music/most-played/10/songs.json

struct SearchResponse: Decodable {
let feed: Feed
}

struct Feed: Decodable {
let title: String
let results: [Item]
}

struct Item: Decodable {
let artistName: String
let id: String
let name: String
let artworkUrl100: URL
let releaseDate: Date
let url: URL
}

解碼的 decoder。

let decoder = JSONDecoder()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
decoder.dateDecodingStrategy = .formatted(dateFormatter)
let searchResponse = try decoder.decode(SearchResponse.self, from: data)
  • Random User Generator

https://randomuser.me/api/?results=10

struct UsersResponse: Decodable {
let results: [User]
}

struct User: Decodable {
let gender: String
let name: Name
let email: String
let picture: Picture
let dob: Dob
let location: Location
}

struct Name: Decodable {
let title: String
let first: String
let last: String
}

struct Picture: Decodable {
let large: String
let medium: String
let thumbnail: String
}

struct Dob: Decodable {
let date: Date
let age: Int
}

struct Location: Decodable {
let city: String
let country: String
let state: String
let coordinates: Coordinate
let street: Street
}

struct Coordinate: Decodable {
let latitude: String
let longitude: String
}

struct Street: Decodable {
let number: Int
let name: String
}

解碼的 decoder。

let decoder = JSONDecoder()
let dateFormatter = ISO8601DateFormatter()
dateFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
decoder.dateDecodingStrategy = .custom({ decoder in
let container = try decoder.singleValueContainer()
let dateString = try container.decode(String.self)
if let date = dateFormatter.date(from: dateString) {
return date
} else {
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid date format")
}
})
let usersResponse = try decoder.decode(UsersResponse.self, from: data)
  • GitHub

https://api.github.com/users/twostraws/followers

struct Follower: Decodable {
let login: String
let id: Int
let avatarUrl: URL
let htmlUrl: URL
let reposUrl: URL
}

解碼的 decoder。

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let followers = try decoder.decode([Follower].self, from: data)
  • IG

https://www.instagram.com/rogerfederer/?__a=1&__d=dis

struct IGResponse: Decodable {
let graphql: Graphql
}

struct Graphql: Decodable {
let user: User
}

struct User: Decodable {
let biography: String
let fullName: String
let edgeFollowedBy: Count
let edgeFollow: Count
let profilePicUrl: URL
let edgeOwnerToTimelineMedia: EdgeOwnerToTimelineMedia
}

struct Count: Decodable {
let count: Int
}

struct EdgeOwnerToTimelineMedia: Decodable {
let count: Int
let edges: [Edge]
}

struct Edge: Decodable {
let node: Node

struct Node: Decodable {
let displayUrl: URL
let edgeMediaToCaption: Caption
let edgeMediaToComment: Count
let takenAtTimestamp: Date
let edgeLikedBy: Count
let dimensions: Dimension
let thumbnailResources: [Thumbnail]
}
}

struct Dimension: Decodable {
let height: Int
let width: Int
}

struct Caption: Decodable {
let edges: [TextEdge]
}

struct TextEdge: Decodable {
let node: Node

struct Node: Decodable {
let text: String
}
}

struct Thumbnail: Decodable {
let src: URL
let configWidth: Int
let configHeight: Int
}

解碼的 decoder。

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
decoder.dateDecodingStrategy = .secondsSince1970
let igResponse = try decoder.decode(IGResponse.self, from: data)

--

--

彼得潘的 iOS App Neverland
彼得潘的 100 道 Swift iOS App 謎題

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com