-
Notifications
You must be signed in to change notification settings - Fork 123
/
Copy pathJSON.swift
109 lines (98 loc) · 4.16 KB
/
JSON.swift
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//===----------------------------------------------------------------------===//
//
// This source file is part of the AsyncHTTPClient open source project
//
// Copyright (c) 2022 Apple Inc. and the AsyncHTTPClient project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of AsyncHTTPClient project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import AsyncHTTPClient
import Foundation
import NIOCore
import NIOFoundationCompat
struct Comic: Codable{
var num: Int
var title: String
var day: String
var month: String
var year: String
var img: String
var alt: String
var news: String
var link: String
var transcript: String
}
@main
struct JSON {
static func main() async throws {
try await getJSON()
try await postJSON()
}
static func getJSON() async throws {
let httpClient = HTTPClient(eventLoopGroupProvider: .singleton)
do {
let request = HTTPClientRequest(url: "https://xkcd.com/info.0.json")
let response = try await httpClient.execute(request, timeout: .seconds(30))
print("HTTP head", response)
let body = try await response.body.collect(upTo: 1024 * 1024) // 1 MB
// we use an overload defined in `NIOFoundationCompat` for `decode(_:from:)` to
// efficiently decode from a `ByteBuffer`
let comic = try JSONDecoder().decode(Comic.self, from: body)
dump(comic)
} catch {
print("request failed:", error)
}
// it is important to shutdown the httpClient after all requests are done, even if one failed
try await httpClient.shutdown()
}
static func postJSON() async throws {
let httpClient = HTTPClient(eventLoopGroupProvider: .singleton)
let comic: Comic = Comic(
num: 0,
title: "Adventures of Super Sally",
day: "17",
month: "4",
year: "2025",
img: "https://www.w3.org/Icons/w3c_main.png",
alt: "Adventures of Super Sally, a super hero with many powers",
news: "Today we learn about super heroes!",
link: "http://comics.com/super-sally",
transcript: "Once upon a time, there was a super hero named Super Sally. She had many powers and was a hero to many."
)
do {
var request = HTTPClientRequest(url: "https://httpbin.org/post")
request.headers.add(name: "Content-Type", value: "application/json")
request.headers.add(name: "Accept", value: "application/json")
request.method = .POST
let jsonData = try JSONEncoder().encode(comic)
request.body = .bytes(jsonData)
let response = try await httpClient.execute(request, timeout: .seconds(30))
let responseBody = try await response.body.collect(upTo: 1024 * 1024) // 1 MB
// we use an overload defined in `NIOFoundationCompat` for `decode(_:from:)` to
// efficiently decode from a `ByteBuffer`
// httpbin.org returns a JSON response with what we sent over the HTTP POST request,
// the json should be identical
let returnedComic = try JSONDecoder().decode(Comic.self, from: responseBody)
assert(comic.title == returnedComic.title)
assert(comic.img == returnedComic.img)
assert(comic.alt == returnedComic.alt)
assert(comic.day == returnedComic.day)
assert(comic.month == returnedComic.month)
assert(comic.year == returnedComic.year)
assert(comic.num == returnedComic.num)
assert(comic.transcript == returnedComic.transcript)
assert(comic.news == returnedComic.news)
assert(comic.link == returnedComic.link)
dump(returnedComic)
} catch {
print("request failed:", error)
}
// it is important to shutdown the httpClient after all requests are done, even if one failed
try await httpClient.shutdown()
}
}