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

Swift API返回分配给javaScript变量的JSON。如何读取JSON?,swift,nsurlsession,Swift,Nsurlsession,我使用的是tumblrv1api()。我曾经为特定的JSON准备所有结构。在您可以找到的文档中,返回的JSON被分配给javaScript变量。我不知道如何从变量/JSON读取数据。当我试图读取一些参数时,出现了错误:无法读取数据,因为它的格式不正确。 你知道怎么读JSON吗 let baseUrl = ".tumblr.com/api/read/json" let https = "https://" let userName = "timberland" le

我使用的是tumblrv1api()。我曾经为特定的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"]}]};
var tumblr\u api\u read={“Tumbllog”:{“title”:“Timberland”,“description”:“name”:“Timberland”,“timezone”:“US\/Eastern”,“cname”:false,“feed”:[]},“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,Oct 2015 15:33:36”,“bookmarklet:”0,“mobile:”0,“feed item:”,“from feed id:”0,“unix时间戳”:1446147216,“format:”html”,“reblog key:“tG24PRhC”,“slug:”publish-x-timberland-collaboration-coming,“is submission”:false,“like button”:“reblog button”:“note count”:“70”,“Tumblog”:“{”title:“timberland”,“name:“timberland”,“cname:”false,“url:”http:\/\/timberland.tumblr.com\”,“timezone:”US\/Eastern”,“avatar\u url\u 512:“https:\/\/66.media.tumblr.com\/571109f21077\u 512.png”,“avatar\uURL:”128”https:\/\/66.media.tumblr.com\/avatar\u 571109f21077\u 128.png,“avatar\u url\u 96:“https:\/\/66.media.tumblr.com\/avatar\u 571109f21077\u 96.png”,“avatar\u url\u 64:“https:\/\/66.media.tumblr.com\/avatar\u 571109f21077\u 64.png”,“avatar\u url\u 48:“https:\/\/\/66.media.tumblr.com\/avatar\u 109F210748:”https:\/\/66.media.tumblr.com\/阿凡达571109f21077\u 40.png,“阿凡达url\u 30:“https:\/\/66.media.tumblr.com\/阿凡达571109f21077\u 30.png”,“阿凡达url\u 24:“https:\/\/66.media.tumblr.com\/阿凡达571109f21077\u 24.png”,“阿凡达url\u 16:“https:\/\/66.media.tumblr.com\/阿凡达url\u 109F21077”图片说明“:”发布X Timberland Collaboration即将到来的11月7日:我们与发布品牌的最新合作。标记您的日历。\n(通过发布X Timberland Collaboration)\n,“宽度”:520,“高度”:347,“照片-url-1280”:“https:\/\/66.media.tumblr.com\/55f5b1f0f1076924a8f6221740f430b1\/tumblr\u nwzyc074G11r6oj70o1\u 540.jpg”,“照片-url-500”:目前,图姆布尔尔的新ZZGGGGGGGGGGGGGGGGGGGGGGGGGZZZZGGGGGGG7-111RoJ70O1-10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10",photo-url-100:“https:\/\/66.media.tumblr.com\/55F5B1F0F1076924A8F6221704F430B1\/tumblr\u nwzyc074G11r6oj70o1\u 100.jpg”,“photo-url-75:“https:\/\/66.media.tumblr.com\/55F5F5B1F0F1076924A8F6221740B1\/tumblr\u nwzyc07G11R6OJ70O1\u 75sq.jpg”,“照片”],“tags:“tags”[“Collaberland”,“timberland”,“品牌”;“Publish”],“Publish”;“发布”];

您有一个非常特殊的情况,理想情况下我们应该获得正确格式的JSON,但如果您处于这种情况

我们在这里可以做的是获取响应并将其拆分,以获得实际的JSON,然后再次将其转换为数据,用于
JSONDecoder

将您的
数据任务更新为

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 {

            if let stringData = String(data: data, encoding: String.Encoding.utf8),
                // Splitting the String to get the actual JSON
                var json = stringData.components(separatedBy: "tumblr_api_read = ").last {

                // Removing the ";" at the end
                json.remove(at: json.index(before: String.Index(encodedOffset: json.count - 1)))

                print(json)

                let jsonData = json.data(using: String.Encoding.utf8)!

                let myPost = try jsonDecoder.decode(TumblrJSON.self, from: jsonData)

                DispatchQueue.main.async {
                    print(myPost.posts[0].id)
                }
            }
        } catch {
            print(error.localizedDescription)
        }
    }
    }.resume()
另外,编辑struts以支持nil值,因为json中的一些数据是nil

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]?
}

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?
}
编辑

将所有代码从这里复制到项目中,或者只是一个游乐场,它100%工作

import Foundation
import UIKit

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
}

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

let mainUrl = URL(string: https + userName + baseUrl)!
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 {

            if let stringData = String(data: data, encoding: String.Encoding.utf8),
                // Splitting the String to get the actual JSON
                var json = stringData.components(separatedBy: "tumblr_api_read = ").last {

                // Removing the ";" at the end
                json.remove(at: json.index(before: String.Index(encodedOffset: json.count - 1)))

                print(json)

                let jsonData = json.data(using: String.Encoding.utf8)!

                let myPost = try jsonDecoder.decode(TumblrJSON.self, from: jsonData)

                DispatchQueue.main.async {
                    print(myPost.posts[0].id!)
                }
            }
        } catch {
            print(error.localizedDescription)
        }
    }
    }.resume()

您有一个非常特殊的情况,理想情况下我们应该获得正确格式的JSON,但是如果您处于这种情况

我们在这里可以做的是获取响应并将其拆分,以获得实际的JSON,然后再次将其转换为数据,用于
JSONDecoder

将您的
数据任务更新为

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 {

            if let stringData = String(data: data, encoding: String.Encoding.utf8),
                // Splitting the String to get the actual JSON
                var json = stringData.components(separatedBy: "tumblr_api_read = ").last {

                // Removing the ";" at the end
                json.remove(at: json.index(before: String.Index(encodedOffset: json.count - 1)))

                print(json)

                let jsonData = json.data(using: String.Encoding.utf8)!

                let myPost = try jsonDecoder.decode(TumblrJSON.self, from: jsonData)

                DispatchQueue.main.async {
                    print(myPost.posts[0].id)
                }
            }
        } catch {
            print(error.localizedDescription)
        }
    }
    }.resume()
另外,编辑struts以支持nil值,因为json中的一些数据是nil

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]?
}

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?
}
编辑

将所有代码从这里复制到项目中,或者只是一个游乐场,它100%工作

import Foundation
import UIKit

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
}

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

let mainUrl = URL(string: https + userName + baseUrl)!
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 {

            if let stringData = String(data: data, encoding: String.Encoding.utf8),
                // Splitting the String to get the actual JSON
                var json = stringData.components(separatedBy: "tumblr_api_read = ").last {

                // Removing the ";" at the end
                json.remove(at: json.index(before: String.Index(encodedOffset: json.count - 1)))

                print(json)

                let jsonData = json.data(using: String.Encoding.utf8)!

                let myPost = try jsonDecoder.decode(TumblrJSON.self, from: jsonData)

                DispatchQueue.main.async {
                    print(myPost.posts[0].id!)
                }
            }
        } catch {
            print(error.localizedDescription)
        }
    }
    }.resume()

以下是正确答案和正确结构:

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>
最后,我将“\/”替换为“/”,以生成一个好的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"]}]}
"""

以下是正确答案和正确结构:

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>
最后,我将“\/”替换为“/”,以生成一个好的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"]}]}
"""

告诉我你的JSON值。然后我可以帮你我在描述中添加了JSON结构。我无法附加获得的数据,因为即使是一篇文章,它也有太多的字符。这是一个HTML代码。解码后,由于提到的错误,我无法打印解码的JSON。我在描述中添加了API返回的JSON,以及你的问题,因为你没有对你进行编码r html字符串,然后再插入到后端的json字符串中。从字符串中创建好的数据会很麻烦。显示您的json值。然后我可以帮助您我在描述中添加了json结构。我无法附加获得的数据,因为即使是一篇文章,它也有太多的字符。这是一个html代码。解码后,由于提到的错误,我无法打印解码后的json。我将API返回的JSON添加到了描述中,还有您的问题,因为在后端插入JSON字符串之前,您没有对html字符串进行编码。从字符串创建良好的数据很麻烦。我假设可编码结构