Как мне получить этот определенный набор данных из json api в Swift? - PullRequest
0 голосов
/ 05 октября 2019

В настоящее время я использую Tracker Networks Apex Legends API версии 2. Я пытаюсь получить данные легенды для каждой легенды, а затем смогу показать данные для каждой конкретной легенды. Тем не менее, я не могу найти легкий способ сделать это. Любые идеи о том, как я могу получить что-то вроде ...

Убийцы следопыта - 100 урона - 3000 и т. Д.

И сделать это для каждой легенды.

Ответ JSON:

      {
        "type": "legend",
        "attributes": {
          "id": "legend_8"
        },
        "metadata": {
          "name": "Pathfinder",
          "imageUrl": "https://trackercdn.com/cdn/apex.tracker.gg/legends/pathfinder-tile.png",
          "tallImageUrl": "https://trackercdn.com/cdn/apex.tracker.gg/legends/pathfinder-tall.png",
          "bgImageUrl": "https://trackercdn.com/cdn/apex.tracker.gg/legends/pathfinder-concept-bg-small.jpg",
          "isActive": true
        },
        "expiryDate": "2019-10-04T21:59:04.1270197Z",
        "stats": {
          "kills": {
            "rank": 208,
            "percentile": 99.9,
            "displayName": "Kills",
            "displayCategory": "Combat",
            "category": null,
            "metadata": {},
            "value": 12728,
            "displayValue": "12,728",
            "displayType": "Unspecified"
          },
          "killsAsKillLeader": {
            "rank": 22,
            "percentile": 99.9,
            "displayName": "Kills As Kill Leader",
            "displayCategory": "Combat",
            "category": null,
            "metadata": {},
            "value": 5764,
            "displayValue": "5,764",
            "displayType": "Unspecified"
          },
          "sniperKills": {
            "rank": 990,
            "percentile": 99.7,
            "displayName": "Sniper Kills",
            "displayCategory": "Weapons",
            "category": null,
            "metadata": {},
            "value": 104,
            "displayValue": "104",
            "displayType": "Unspecified"
          },
          "seasonWins": {
            "rank": 31158,
            "percentile": 92,
            "displayName": "Season 1 Wins",
            "displayCategory": "Game",
            "category": null,
            "metadata": {},
            "value": 24,
            "displayValue": "24",
            "displayType": "Unspecified"
          },
          "seasonDamage": {
            "rank": 5310,
            "percentile": 98.8,
            "displayName": "Season 1 Damage",
            "displayCategory": "Game",
            "category": null,
            "metadata": {},
            "value": 403954,
            "displayValue": "403,954",
            "displayType": "Unspecified"
          }
        }
      },

"expiryDate": "2019-10-04T21: 59: 04.1270197Z"}

Вы видите, что я хочу получить эту статистическую информацию для каждой легенды, а затем отобразить их имя с любымданные о них доступны внутри представления коллекции или tableView. Возможно представление коллекции.

Используемые структуры (сделано с QuickType):

struct Store: Codable {
     let data: DataClass
        enum CodingKeys: String, CodingKey {
        case data = "data"
    }
}

// MARK: - DataClass
struct DataClass: Codable {
    let platformInfo: PlatformInfo
    let userInfo: UserInfo
    let metadata: DataMetadata
    let segments: [Segment]
    let availableSegments: [AvailableSegment]
    //let expiryDate: ExpiryDate

    enum CodingKeys: String, CodingKey {
        case platformInfo = "platformInfo"
        case userInfo = "userInfo"
        case metadata = "metadata"
        case segments = "segments"
        case availableSegments = "availableSegments"
        //case expiryDate = "expiryDate"
    }
}

// MARK: - AvailableSegment
struct AvailableSegment: Codable {
    let type: TypeEnum
    let attributes: MetadataClass

    enum CodingKeys: String, CodingKey {
        case type = "type"
        case attributes = "attributes"
    }
}

// MARK: - MetadataClass
struct MetadataClass: Codable {
}

enum TypeEnum: String, Codable {
    case legend = "legend"
    case overview = "overview"
}



// MARK: - DataMetadata
struct DataMetadata: Codable {
    let currentSeason: Int
    let activeLegend: String
    let activeLegendName: String

    enum CodingKeys: String, CodingKey {
        case currentSeason = "currentSeason"
        case activeLegend = "activeLegend"
        case activeLegendName = "activeLegendName"
    }
}

// MARK: - PlatformInfo
struct PlatformInfo: Codable {
    let platformSlug: String
    let platformUserId: String
    let platformUserHandle: String
    let platformUserIdentifier: String
    let avatarUrl: String
    let additionalParameters: JSONNull?

    enum CodingKeys: String, CodingKey {
        case platformSlug = "platformSlug"
        case platformUserId = "platformUserId"
        case platformUserHandle = "platformUserHandle"
        case platformUserIdentifier = "platformUserIdentifier"
        case avatarUrl = "avatarUrl"
        case additionalParameters = "additionalParameters"
    }
}

// MARK: - Segment
struct Segment: Codable {
    let type: TypeEnum
    let attributes: SegmentAttributes
    let metadata: SegmentMetadata
   // let expiryDate: ExpiryDate
    let stats: Stats

    enum CodingKeys: String, CodingKey {
        case type = "type"
        case attributes = "attributes"
        case metadata = "metadata"
        //case expiryDate = "expiryDate"
        case stats = "stats"
    }
}

// MARK: - SegmentAttributes
struct SegmentAttributes: Codable {
    let id: String?

    enum CodingKeys: String, CodingKey {
        case id = "id"
    }
}

// MARK: - SegmentMetadata
struct SegmentMetadata: Codable {
    let name: String
    let imageUrl: String?
    let tallImageUrl: String?
    let bgImageUrl: String?
    let isActive: Bool?

    enum CodingKeys: String, CodingKey {
        case name = "name"
        case imageUrl = "imageUrl"
        case tallImageUrl = "tallImageUrl"
        case bgImageUrl = "bgImageUrl"
        case isActive = "isActive"
    }
}

// MARK: - Stats
struct Stats: Codable {
    let level: ArKills?
    let kills: ArKills
    let damage: ArKills?
    let headshots: ArKills?
    let finishers: ArKills?
    let arKills: ArKills?
    let carePackageKills: ArKills?
    let seasonWins: ArKills?
    let seasonKills: ArKills?
    let season2Wins: ArKills?
    let rankScore: RankScore?
    let smokeGrenadeEnemiesHit: ArKills?
    let eyeEnemiesScanned: ArKills?
    let grappleTravelDistance: ArKills?

    enum CodingKeys: String, CodingKey {
        case level = "level"
        case kills = "kills"
        case damage = "damage"
        case headshots = "headshots"
        case finishers = "finishers"
        case arKills = "arKills"
        case carePackageKills = "carePackageKills"
        case seasonWins = "seasonWins"
        case seasonKills = "seasonKills"
        case season2Wins = "season2Wins"
        case rankScore = "rankScore"
        case smokeGrenadeEnemiesHit = "smokeGrenadeEnemiesHit"
        case eyeEnemiesScanned = "eyeEnemiesScanned"
        case grappleTravelDistance = "grappleTravelDistance"
    }
}

// MARK: - ArKills
struct ArKills: Codable {
    let rank: Int?
    let percentile: Double?
    let displayName: String
    let displayCategory: DisplayCategory
    let category: JSONNull?
    let metadata: MetadataClass
    let value: Double
    let displayValue: String
    let displayType: DisplayType

    enum CodingKeys: String, CodingKey {
        case rank = "rank"
        case percentile = "percentile"
        case displayName = "displayName"
        case displayCategory = "displayCategory"
        case category = "category"
        case metadata = "metadata"
        case value = "value"
        case displayValue = "displayValue"
        case displayType = "displayType"
    }
}

enum DisplayCategory: String, Codable {
    case combat = "Combat"
    case game = "Game"
    case weapons = "Weapons"
}

enum DisplayType: String, Codable {
    case unspecified = "Unspecified"
}

// MARK: - RankScore
struct RankScore: Codable {
    let rank: JSONNull?
    let percentile: Int
    let displayName: String
    let displayCategory: DisplayCategory
    let category: JSONNull?
    let metadata: RankScoreMetadata
    let value: Int
    let displayValue: String
    let displayType: DisplayType

    enum CodingKeys: String, CodingKey {
        case rank = "rank"
        case percentile = "percentile"
        case displayName = "displayName"
        case displayCategory = "displayCategory"
        case category = "category"
        case metadata = "metadata"
        case value = "value"
        case displayValue = "displayValue"
        case displayType = "displayType"
    }
}

// MARK: - RankScoreMetadata
struct RankScoreMetadata: Codable {
    let iconUrl: String

    enum CodingKeys: String, CodingKey {
        case iconUrl = "iconUrl"
    }
}

// MARK: - UserInfo
struct UserInfo: Codable {
    let isPremium: Bool
    let isVerified: Bool
    let isInfluencer: Bool
    let countryCode: String
    let customAvatarUrl: JSONNull?
    let socialAccounts: JSONNull?

    enum CodingKeys: String, CodingKey {
        case isPremium = "isPremium"
        case isVerified = "isVerified"
        case isInfluencer = "isInfluencer"
        case countryCode = "countryCode"
        case customAvatarUrl = "customAvatarUrl"
        case socialAccounts = "socialAccounts"
    }
}

// MARK: - Encode/decode helpers

class JSONNull: Codable, Hashable {

    public static func == (lhs: JSONNull, rhs: JSONNull) -> Bool {
        return true
    }

    public var hashValue: Int {
        return 0
    }

    public func hash(into hasher: inout Hasher) {
        // No-op
    }

    public init() {}

    public required init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if !container.decodeNil() {
            throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull"))
        }
    }

    public func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encodeNil()
    }
}  

Код, используемый для вызова API и отображения данных:

    let PlayerStatURL = URL(string: "https://public-api.tracker.gg/v2/apex/standard/profile/origin/itsspress")

        if let unwrappedURL = PlayerStatURL {
            var request = URLRequest(url: unwrappedURL)
            request.addValue("db833c37-1f45-4be4-a670-38272dba7504", forHTTPHeaderField: "TRN-Api-Key")
            let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
                // you should put in error handling code, too
                if let data = data {
                    do {


                        let store = try JSONDecoder().decode(Store.self, from: data) as Store

                        print(store.data.platformInfo.avatarUrl)
                        print(store.data.platformInfo.platformUserHandle)
                        print("Level: \(store.data.segments[0].stats.level!.displayValue)")

                        print("lifetime Kills: \(store.data.segments.map{$0.stats.kills.displayValue}[0])")

                        print(store.data.segments.map{$0.metadata.name})
                        print(store.data.segments.map{$0.stats.carePackageKills?.displayName}[2])


                    } catch {
                        print(error.localizedDescription)
                        print(error)

                        }
                    }
                }
            dataTask.resume()

        }  

Я не уверен, какполучить эти данные из вышеуказанного JSON. Кажется, структура только позволяет мне извлекать, скажем, убить статистику из всех легенд, и не позволяет мне просто извлекать, скажем, из Pathfinder.

Как я могу просто получить статистику из Pathfinder?

1 Ответ

0 голосов
/ 24 октября 2019

Вы можете достичь этого, как показано ниже,

do {
    let store = try JSONDecoder().decode(Store.self, from: data) as Store
    store.data.segments.map{$0.metadata.name}.forEach { legendName in
        if let stats = store.data.segments.first(where: { $0.metadata.name == legendName })?.stats {        
            let killString = stats.kills.displayName + " - " + stats.kills.displayValue
            var damageString: String = ""
            if let damage = stats.damage {
                damageString = damage.displayName + " - " + damage.displayValue
            }
            print(legendName + " " + killString + " " + damageString )
        }
    }
} catch {
    print(error.localizedDescription)
    print(error)

}

Вывод:

Lifetime Kills - 408 Damage - 74,053
Pathfinder Kills - 230 Damage - 59,694
Gibraltar Kills - 1 
Bangalore Kills - 116 
Octane Kills - 0 
Bloodhound Kills - 6 
Wraith Kills - 18 Damage - 6,357
Mirage Kills - 14 Damage - 5,307
Caustic Kills - 7 Damage - 2,695
Lifeline Kills - 16 
...