Json在Swift中解析,当一个键值从Json本身获取



我有一个json下面需要解析,我已经研究了许多解决方案。这里我需要使用开始键的值来获取下一个值。

"journey": {
"start": "The6422Dcd89Dc070B243Da5743",
"6422dcd89dc070b243da5743": {
"events": [
{
"event_id": "4af5dbc5-b8ae-492d-aa97-16bb9b0967c9",
"type": "sale",
"name": "SALE"
}
我创建了一个结构体
// MARK: - Journey
struct Journey: Codable {
let start: String?
let value: The6422Dcd89Dc070B243Da5743?
let summary: [Summary]?
enum CodingKeys: String, CodingKey {
case start
case value = "6422dcd89dc070b243da5743"
case summary
}
}

如何使它动态?

你的问题有点难弄清楚,因为你的JSON似乎实际上不匹配你的结构,但假设问题实际上是关键是在start,你会解码它与AnyCodingKey。(实现AnyCodingKey的方法有很多;这是最简单的。

struct AnyCodingKey: CodingKey {
var stringValue: String = ""
init?(stringValue: String) { self.stringValue = stringValue }
var intValue: Int?
init?(intValue: Int) { self.intValue = intValue }
}

这样,您将首先解码start,然后解码相同容器中的值:

struct Journey: Decodable {
let start: String
let summary: Summary
// This is the only static key
enum CodingKeys: String, CodingKey {
case start
}
init(from decoder: Decoder) throws {
// First, decode the static things
let container = try decoder.container(keyedBy: CodingKeys.self)
self.start = try container.decode(String.self, forKey: .start)
// Now decode the dynamic things using AnyCodingKey
let dynamic = try decoder.container(keyedBy: AnyCodingKey.self)
self.summary = try dynamic.decode(Summary.self, 
forKey: AnyCodingKey(stringValue: self.start))
}
}

这是同一件事的不同版本,它根本不需要静态CodingKeys(有时这很好,有时这只是额外的开销)。通过创建稍微高级一点的AnyCodingKey版本,您可以获得稍微好一点的语法。(这是我真正使用的AnyCodingKey版本。)

public struct AnyCodingKey: CodingKey, CustomStringConvertible, ExpressibleByStringLiteral,
ExpressibleByIntegerLiteral, Hashable, Comparable {
public var description: String { stringValue }
public let stringValue: String
public init(_ string: String) { self.stringValue = string }
public init?(stringValue: String) { self.init(stringValue) }
public var intValue: Int?
public init(intValue: Int) {
self.stringValue = "(intValue)"
self.intValue = intValue
}
public init(stringLiteral value: String) { self.init(value) }
public init(integerLiteral value: Int) { self.init(intValue: value) }
public static func < (lhs: AnyCodingKey, rhs: AnyCodingKey) -> Bool {
lhs.stringValue < rhs.stringValue
}
}
struct Journey: Codable {
let start: String
let summary: Summary
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: AnyCodingKey.self)
// First, decode the static things.
// Note how you can use a string literal as a key with AnyCodingKey.
self.start = try container.decode(String.self, forKey: "start")
// Now decode the dynamic things
// Note that you have to convert the String to AnyCodingKey.
// Above, it is keyed on a String **literal**, which can automatically
// convert to AnyCodingKey. That doesn't mean you can key with a String.
self.summary = try container.decode(Summary.self, 
forKey: AnyCodingKey(self.start))
}
}

最新更新