swift - API 返回分配给 javaScript 变量的 JSON。如何读取该 JSON?

标签 swift nsurlsession

我正在使用 Tumblr v1 API ( https://www.tumblr.com/docs/en/api/v1 )。我用了https://app.quicktype.io为特定的 JSON 准备所有结构。在该文档中,您可以找到返回的 JSON 分配给 javaScript 变量。我不知道如何从该变量/JSON 中读取数据。当我尝试读取一些参数时出现错误:无法读取数据,因为它的格式不正确。 你知道如何阅读那个 JSON 吗?

    let baseUrl = ".tumblr.com/api/read/json"
    let https = "https://"
    let userName = "timberland"
    let jsonDecoder = JSONDecoder()

    guard let mainUrl = URL(string: https + userName + baseUrl) else { return }
    let urlSession = URLSession.shared

    urlSession.dataTask(with: mainUrl) { (data, response, error) in
        if let error = error {
            print(error.localizedDescription)
        }

        guard let httpResponse = response as? HTTPURLResponse else { return }
        if httpResponse.statusCode == 200 {
            guard let data = data else { return }
            do {
                let myPost = try jsonDecoder.decode(TumblrJSON.self, from: data)
                DispatchQueue.main.async {
                    print(myPost.posts[0].id)
                }
            } catch {
                print(error.localizedDescription)
            }
        }
    }.resume()

和 JSON 结构

    struct TumblrJSON: Codable {
    let tumblelog: TumblrJSONTumblelog
    let postsStart, postsTotal: Int
    let postsType: Bool
    let posts: [Post]

    enum CodingKeys: String, CodingKey {
        case tumblelog
        case postsStart = "posts-start"
        case postsTotal = "posts-total"
        case postsType = "posts-type"
        case posts
    }
}

struct Post: Codable {
    let id: String
    let url, urlWithSlug: String
    let type, dateGmt, date: String
    let bookmarklet, mobile: Int
    let feedItem: String
    let fromFeedID, unixTimestamp: Int
    let format, reblogKey, slug: String
    let isSubmission: Bool
    let likeButton, reblogButton, state, noteCount: String
    let tumblelog: PostTumblelog
    let regularTitle, regularBody: String
    let tags: [String]

    enum CodingKeys: String, CodingKey {
        case id, url
        case urlWithSlug = "url-with-slug"
        case type
        case dateGmt = "date-gmt"
        case date, bookmarklet, mobile
        case feedItem = "feed-item"
        case fromFeedID = "from-feed-id"
        case unixTimestamp = "unix-timestamp"
        case format
        case reblogKey = "reblog-key"
        case slug
        case isSubmission = "is-submission"
        case likeButton = "like-button"
        case reblogButton = "reblog-button"
        case state
        case noteCount = "note-count"
        case tumblelog
        case regularTitle = "regular-title"
        case regularBody = "regular-body"
        case tags
    }
}

struct PostTumblelog: Codable {
    let title, name: String
    let cname: Bool
    let url: String
    let timezone: String
    let avatarURL512, avatarURL128, avatarURL96, avatarURL64: String
    let avatarURL48, avatarURL40, avatarURL30, avatarURL24: String
    let avatarURL16: String

    enum CodingKeys: String, CodingKey {
        case title, name, cname, url, timezone
        case avatarURL512 = "avatar_url_512"
        case avatarURL128 = "avatar_url_128"
        case avatarURL96 = "avatar_url_96"
        case avatarURL64 = "avatar_url_64"
        case avatarURL48 = "avatar_url_48"
        case avatarURL40 = "avatar_url_40"
        case avatarURL30 = "avatar_url_30"
        case avatarURL24 = "avatar_url_24"
        case avatarURL16 = "avatar_url_16"
    }
}

struct TumblrJSONTumblelog: Codable {
    let title, description, name, timezone: String
    let cname: Bool
}

JSON 值

var tumblr_api_read = {"tumblelog":{"title":"Timberland","description":"","name":"timberland","timezone":"US\/Eastern","cname":false,"feeds":[]},"posts-start":0,"posts-total":493,"posts-type":false,"posts":[{"id":"132163144823","url":"http:\/\/timberland.tumblr.com\/post\/132163144823","url-with-slug":"http:\/\/timberland.tumblr.com\/post\/132163144823\/publish-x-timberland-collaboration-coming","type":"photo","date-gmt":"2015-10-29 19:33:36 GMT","date":"Thu, 29 Oct 2015 15:33:36","bookmarklet":0,"mobile":0,"feed-item":"","from-feed-id":0,"unix-timestamp":1446147216,"format":"html","reblog-key":"tG24PRhC","slug":"publish-x-timberland-collaboration-coming","is-submission":false,"like-button":"<div class=\"like_button\" data-post-id=\"132163144823\" data-blog-name=\"timberland\" id=\"like_button_132163144823\"><iframe id=\"like_iframe_132163144823\" src=\"https:\/\/assets.tumblr.com\/assets\/html\/like_iframe.html?_v=66c22ab5319d742bca5762b8d18f9d06#name=timberland&amp;post_id=132163144823&amp;color=black&amp;rk=tG24PRhC\" scrolling=\"no\" width=\"20\" height=\"20\" frameborder=\"0\" class=\"like_toggle\" allowTransparency=\"true\" name=\"like_iframe_132163144823\"><\/iframe><\/div>","reblog-button":"<a href=\"https:\/\/www.tumblr.com\/reblog\/132163144823\/tG24PRhC\" class=\"reblog_button\"style=\"display: block;width:20px;height:20px;\"><svg width=\"100%\" height=\"100%\" viewBox=\"0 0 21 21\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" xmlns:xlink=\"http:\/\/www.w3.org\/1999\/xlink\" fill=\"#000\"><path d=\"M5.01092527,5.99908429 L16.0088498,5.99908429 L16.136,9.508 L20.836,4.752 L16.136,0.083 L16.1360004,3.01110845 L2.09985349,3.01110845 C1.50585349,3.01110845 0.979248041,3.44726568 0.979248041,4.45007306 L0.979248041,10.9999998 L3.98376463,8.30993634 L3.98376463,6.89801007 C3.98376463,6.20867902 4.71892527,5.99908429 5.01092527,5.99908429 Z\"><\/path><path d=\"M17.1420002,13.2800293 C17.1420002,13.5720293 17.022957,14.0490723 16.730957,14.0490723 L4.92919922,14.0490723 L4.92919922,11 L0.5,15.806 L4.92919922,20.5103758 L5.00469971,16.9990234 L18.9700928,16.9990234 C19.5640928,16.9990234 19.9453125,16.4010001 19.9453125,15.8060001 L19.9453125,9.5324707 L17.142,12.203\"><\/path><\/svg><\/a>","note-count":"70","tumblelog":{"title":"Timberland","name":"timberland","cname":false,"url":"http:\/\/timberland.tumblr.com\/","timezone":"US\/Eastern","avatar_url_512":"https:\/\/66.media.tumblr.com\/avatar_571109f21077_512.png","avatar_url_128":"https:\/\/66.media.tumblr.com\/avatar_571109f21077_128.png","avatar_url_96":"https:\/\/66.media.tumblr.com\/avatar_571109f21077_96.png","avatar_url_64":"https:\/\/66.media.tumblr.com\/avatar_571109f21077_64.png","avatar_url_48":"https:\/\/66.media.tumblr.com\/avatar_571109f21077_48.png","avatar_url_40":"https:\/\/66.media.tumblr.com\/avatar_571109f21077_40.png","avatar_url_30":"https:\/\/66.media.tumblr.com\/avatar_571109f21077_30.png","avatar_url_24":"https:\/\/66.media.tumblr.com\/avatar_571109f21077_24.png","avatar_url_16":"https:\/\/66.media.tumblr.com\/avatar_571109f21077_16.png"},"photo-caption":"<b>Publish X Timberland Collaboration<\/b><br\/><br\/><p>Coming November 7: our latest collaboration with Publish Brand. Mark your calendars. <\/p><p>\n        (via <a href=\"http:\/\/pco.lt\/1O3sTq4\">Publish X Timberland Collaboration<\/a>)\n    <\/p>","width":520,"height":347,"photo-url-1280":"https:\/\/66.media.tumblr.com\/55f5b1f0f1076924a8f6221740f430b1\/tumblr_nwzyc074G11r6oj70o1_540.jpg","photo-url-500":"https:\/\/66.media.tumblr.com\/55f5b1f0f1076924a8f6221740f430b1\/tumblr_nwzyc074G11r6oj70o1_500.jpg","photo-url-400":"https:\/\/66.media.tumblr.com\/55f5b1f0f1076924a8f6221740f430b1\/tumblr_nwzyc074G11r6oj70o1_400.jpg","photo-url-250":"https:\/\/66.media.tumblr.com\/55f5b1f0f1076924a8f6221740f430b1\/tumblr_nwzyc074G11r6oj70o1_250.jpg","photo-url-100":"https:\/\/66.media.tumblr.com\/55f5b1f0f1076924a8f6221740f430b1\/tumblr_nwzyc074G11r6oj70o1_100.jpg","photo-url-75":"https:\/\/66.media.tumblr.com\/55f5b1f0f1076924a8f6221740f430b1\/tumblr_nwzyc074G11r6oj70o1_75sq.jpg","photos":[],"tags":["collab","timberland","publishbrand","timberlandxpublish"]}]};

最佳答案

这是具有正确结构的正确答案:

struct MyJsonStruct: Codable {
    let tumblelog: PostTumblelog?
    let postsStart: Int?
    let postsTotal: Int?
    let postsType: Bool?
    let posts : [Post]

    enum CodingKeys: String, CodingKey {
        case tumblelog = "tumblelog"
        case postsStart = "posts-start"
        case postsTotal = "posts-total"
        case postsType = "posts-type"
        case posts
    }
}

struct Post: Codable {
    let id: String?
    let url, urlWithSlug: String?
    let type, dateGmt, date: String?
    let bookmarklet, mobile: Int?
    let feedItem: String?
    let fromFeedID, unixTimestamp: Int?
    let format, reblogKey, slug: String?
    let isSubmission: Bool?
    let likeButton, reblogButton, state, noteCount: String?
    let tumblelog: PostTumblelog?
    let photoCaption: String?
    let width, height: Int?
    let tags: [String]?
    let photoUrl1280 : String?
    let photoUrl500 : String?
    let photoUrl400 : String?
    let photoUrl250 : String?
    let photoUrl100 : String?
    let photoUrl75 : String?
    let photos : [String]?

    enum CodingKeys: String, CodingKey {
        case id, url
        case urlWithSlug = "url-with-slug"
        case type
        case dateGmt = "date-gmt"
        case date, bookmarklet, mobile
        case feedItem = "feed-item"
        case fromFeedID = "from-feed-id"
        case unixTimestamp = "unix-timestamp"
        case format
        case reblogKey = "reblog-key"
        case slug
        case isSubmission = "is-submission"
        case likeButton = "like-button"
        case reblogButton = "reblog-button"
        case state
        case noteCount = "note-count"
        case tumblelog
        case photoCaption = "photo-caption"
        case width, height
        case photoUrl1280 = "photo-url-1280"
        case photoUrl500 = "photo-url-500"
        case photoUrl400 = "photo-url-400"
        case photoUrl250 = "photo-url-250"
        case photoUrl100 = "photo-url-100"
        case photoUrl75 = "photo-url-75"
        case photos
        case tags
    }
}

struct PostTumblelog: Codable {
    let title, name: String?
    let description : String? = ""
    let cname: Bool?
    let url: String?
    let timezone: String?
    let feeds : [String]? = []
    let avatarURL512, avatarURL128, avatarURL96, avatarURL64: String?
    let avatarURL48, avatarURL40, avatarURL30, avatarURL24: String?
    let avatarURL16: String?

    enum CodingKeys: String, CodingKey {
        case title, name, cname, url, timezone
        case avatarURL512 = "avatar_url_512"
        case avatarURL128 = "avatar_url_128"
        case avatarURL96 = "avatar_url_96"
        case avatarURL64 = "avatar_url_64"
        case avatarURL48 = "avatar_url_48"
        case avatarURL40 = "avatar_url_40"
        case avatarURL30 = "avatar_url_30"
        case avatarURL24 = "avatar_url_24"
        case avatarURL16 = "avatar_url_16"
    }
}

我像下面这样调用解码器:

    let jsonData = json.data(using: .utf8)!
    do {

        let myPost = try JSONDecoder().decode(MyJsonStruct.self, from: jsonData)

        print(myPost)
    } catch {
        print(error)
    }

此外,您以错误的方式构建了 json 字符串:在后端插入到 json 字符串之前需要对 html 字符串进行编码,请参见示例:

<b>Publish X Timberland Collaboration</b><br/><br/><p>Coming November 7: our latest collaboration with Publish Brand. Mark your calendars. </p><p>

    </p>

需要编码为

%3Cb%3EPublish+X+Timberland+Collaboration%3C%2Fb%3E%3Cbr%2F%3E%3Cbr%2F%3E%3Cp%3EComing+November+7%3A+our+latest+collaboration+with+Publish+Brand.+Mark+your+calendars.+%3C%2Fp%3E%3Cp%3E%0D%0A++++++++%0D%0A++++%3C%2Fp%3E

最后,我将出现的“\/”替换为“/”以制作一个好的 json 字符串。 之后,您可以轻松地在 swift 中处理 json 数据。

而且我们有这样的 json 字符串:

var json = """
{"tumblelog": {"title": "Timberland","description": "","name": "timberland","timezone": "US/Eastern","cname": false,"feeds": []},"posts-start": 0,"posts-total": 493,"posts-type": false,"posts": [{"id": "132163144823","url": "http://timberland.tumblr.com/post/132163144823","url-with-slug": "http://timberland.tumblr.com/post/132163144823/publish-x-timberland-collaboration-coming","type": "photo","date-gmt": "2015-10-29 19:33:36 GMT","date": "Thu, 29 Oct 2015 15:33:36","bookmarklet": 0,"mobile": 0,"feed-item": "","from-feed-id": 0,"unix-timestamp": 1446147216,"format": "html","reblog-key": "tG24PRhC","slug": "publish-x-timberland-collaboration-coming","is-submission": false,"like-button": "%3Cdiv%20class%3D%5C%22like_button%5C%22%20data-post-id%3D%5C%22132163144823%5C%22%20data-blog-name%3D%5C%22timberland%5C%22%20id%3D%5C%22like_button_132163144823%5C%22%3E%3Ciframe%20id%3D%5C%22like_iframe_132163144823%5C%22%20src%3D%5C%22https%3A%5C%2F%5C%2Fassets.tumblr.com%5C%2Fassets%5C%2Fhtml%5C%2Flike_iframe.html%3F_v%3D66c22ab5319d742bca5762b8d18f9d06%23name%3Dtimberland%26amp%3Bpost_id%3D132163144823%26amp%3Bcolor%3Dblack%26amp%3Brk%3DtG24PRhC%5C%22%20scrolling%3D%5C%22no%5C%22%20width%3D%5C%2220%5C%22%20height%3D%5C%2220%5C%22%20frameborder%3D%5C%220%5C%22%20class%3D%5C%22like_toggle%5C%22%20allowTransparency%3D%5C%22true%5C%22%20name%3D%5C%22like_iframe_132163144823%5C%22%3E%3C%5C%2Fiframe%3E%3C%5C%2Fdiv%3E","reblog-button": "%3Ca%20href%3D%5C%22https%3A%5C%2F%5C%2Fwww.tumblr.com%5C%2Freblog%5C%2F132163144823%5C%2FtG24PRhC%5C%22%20class%3D%5C%22reblog_button%5C%22style%3D%5C%22display%3A%20block%3Bwidth%3A20px%3Bheight%3A20px%3B%5C%22%3E%3Csvg%20width%3D%5C%22100%25%5C%22%20height%3D%5C%22100%25%5C%22%20viewBox%3D%5C%220%200%2021%2021%5C%22%20xmlns%3D%5C%22http%3A%5C%2F%5C%2Fwww.w3.org%5C%2F2000%5C%2Fsvg%5C%22%20xmlns%3Axlink%3D%5C%22http%3A%5C%2F%5C%2Fwww.w3.org%5C%2F1999%5C%2Fxlink%5C%22%20fill%3D%5C%22%23000%5C%22%3E%3Cpath%20d%3D%5C%22M5.01092527%2C5.99908429%20L16.0088498%2C5.99908429%20L16.136%2C9.508%20L20.836%2C4.752%20L16.136%2C0.083%20L16.1360004%2C3.01110845%20L2.09985349%2C3.01110845%20C1.50585349%2C3.01110845%200.979248041%2C3.44726568%200.979248041%2C4.45007306%20L0.979248041%2C10.9999998%20L3.98376463%2C8.30993634%20L3.98376463%2C6.89801007%20C3.98376463%2C6.20867902%204.71892527%2C5.99908429%205.01092527%2C5.99908429%20Z%5C%22%3E%3C%5C%2Fpath%3E%3Cpath%20d%3D%5C%22M17.1420002%2C13.2800293%20C17.1420002%2C13.5720293%2017.022957%2C14.0490723%2016.730957%2C14.0490723%20L4.92919922%2C14.0490723%20L4.92919922%2C11%20L0.5%2C15.806%20L4.92919922%2C20.5103758%20L5.00469971%2C16.9990234%20L18.9700928%2C16.9990234%20C19.5640928%2C16.9990234%2019.9453125%2C16.4010001%2019.9453125%2C15.8060001%20L19.9453125%2C9.5324707%20L17.142%2C12.203%5C%22%3E%3C%5C%2Fpath%3E%3C%5C%2Fsvg%3E%3C%5C%2Fa%3E","note-count": "70","tumblelog": {"title": "Timberland","name": "timberland","cname": false,"url": "http://timberland.tumblr.com/","timezone": "US/Eastern","avatar_url_512": "https://66.media.tumblr.com/avatar_571109f21077_512.png","avatar_url_128": "https://66.media.tumblr.com/avatar_571109f21077_128.png","avatar_url_96": "https://66.media.tumblr.com/avatar_571109f21077_96.png","avatar_url_64": "https://66.media.tumblr.com/avatar_571109f21077_64.png","avatar_url_48": "https://66.media.tumblr.com/avatar_571109f21077_48.png","avatar_url_40": "https://66.media.tumblr.com/avatar_571109f21077_40.png","avatar_url_30": "https://66.media.tumblr.com/avatar_571109f21077_30.png","avatar_url_24": "https://66.media.tumblr.com/avatar_571109f21077_24.png","avatar_url_16": "https://66.media.tumblr.com/avatar_571109f21077_16.png"},"photo-caption": "%3Cb%3EPublish%20X%20Timberland%20Collaboration%3C%5C%2Fb%3E%3Cbr%5C%2F%3E%3Cbr%5C%2F%3E%3Cp%3EComing%20November%207%3A%20our%20latest%20collaboration%20with%20Publish%20Brand.%20Mark%20your%20calendars.%20%3C%5C%2Fp%3E%3Cp%3E%5Cn%20%20%20%20%20%20%20%20(via%20%3Ca%20href%3D%5C%22http%3A%5C%2F%5C%2Fpco.lt%5C%2F1O3sTq4%5C%22%3EPublish%20X%20Timberland%20Collaboration%3C%5C%2Fa%3E)%5Cn%20%20%20%20%3C%5C%2Fp%3E","width": 520,"height": 347,"photo-url-1280": "https://66.media.tumblr.com/55f5b1f0f1076924a8f6221740f430b1/tumblr_nwzyc074G11r6oj70o1_540.jpg","photo-url-500": "https://66.media.tumblr.com/55f5b1f0f1076924a8f6221740f430b1/tumblr_nwzyc074G11r6oj70o1_500.jpg","photo-url-400": "https://66.media.tumblr.com/55f5b1f0f1076924a8f6221740f430b1/tumblr_nwzyc074G11r6oj70o1_400.jpg","photo-url-250": "https://66.media.tumblr.com/55f5b1f0f1076924a8f6221740f430b1/tumblr_nwzyc074G11r6oj70o1_250.jpg","photo-url-100": "https://66.media.tumblr.com/55f5b1f0f1076924a8f6221740f430b1/tumblr_nwzyc074G11r6oj70o1_100.jpg","photo-url-75": "https://66.media.tumblr.com/55f5b1f0f1076924a8f6221740f430b1/tumblr_nwzyc074G11r6oj70o1_75sq.jpg","photos": [],"tags": ["collab", "timberland", "publishbrand", "timberlandxpublish"]}]}
"""

关于swift - API 返回分配给 javaScript 变量的 JSON。如何读取该 JSON?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55661044/

相关文章:

ios - 在为另一个节点使用灯光后保持原始节点照明

xamarin.ios - iOS8:backgroundSessionConfiguration 已弃用

ios - NSURLSession,重试加载数据

ios - 使用 StoreKit 的未记录的 NSURLErrorDomain 错误代码(-1001、-1003 和 -1004)

ios - URLSessionDownloadTask 启动时调用的委托(delegate)方法是什么?

ios - 如何从 Swift 4 中的解码器容器获取非解码属性?

ios - 标签的 UITest 颜色(不是 UI 标签)

swift - 为什么这个 [Int]-Element 不是 'Int' 类型的?

ios - 使用 Facebook SDK 登录从一个 Storyboard转到另一个 Storyboard

json - 如何使用 NSOperationQueue 和 NSBlockOperation 在 Swift 中使 JSON 响应异步?