Swift codable-如何获取位于层次结构中较高位置的结构的属性值? 试图重构一些遗留JSON解析代码以使用可重用并试图重用现有SWIFT结构,为简单起见,请考虑以下JSON: { "dateOfBirth":"2016-05-19" ... "discountOffer":[ { "discountName":"Discount1" ... }, { "discountName":"Discount2" ... } ] }

Swift codable-如何获取位于层次结构中较高位置的结构的属性值? 试图重构一些遗留JSON解析代码以使用可重用并试图重用现有SWIFT结构,为简单起见,请考虑以下JSON: { "dateOfBirth":"2016-05-19" ... "discountOffer":[ { "discountName":"Discount1" ... }, { "discountName":"Discount2" ... } ] },swift,struct,hierarchy,decodable,Swift,Struct,Hierarchy,Decodable,在遗留代码中,Swift struct Discount有一个属性'discountType',其值是根据从JSON获得的成员结构的'dateOfBirth'计算的,问题是,如何将成员的dateOfBirth传递给每个折扣结构?或者层次结构中较低的结构是否有办法访问层次结构中较高的结构 struct Member: Codable { var dateOfBirth: Date? var discounts: [Discount]? } struct Discount: Co

在遗留代码中,Swift struct Discount有一个属性'discountType',其值是根据从JSON获得的成员结构的'dateOfBirth'计算的,问题是,如何将成员的dateOfBirth传递给每个折扣结构?或者层次结构中较低的结构是否有办法访问层次结构中较高的结构

struct Member: Codable {
    var dateOfBirth: Date?
    var discounts: [Discount]?

}

struct Discount: Codable {
    var discountName: String?
    var memberDateOfBirth: Date? // *** Need to get it from Member but how?
    var discountType: String? // *** Will be determined by Member's dateOfBirth

    public init(from decoder: Decoder) throws {
        // self.memberDateOfBirth = // *** How to set from Member's dateOfBirth?????
        // use self.memberDateOfBirth to determine discountType
      ...
    }

}
我无法使用解码器的userInfo作为get属性。我曾想过将dateOfBirth设置为某个静态变量,但听起来像是一个难题


非常感谢您的帮助。谢谢。

您可以这样访问它们

init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        self.memberDateOfBirth = try values.decode(T.self, forKey: .result) //and whatever you want to do
        serverErrors = try values.decode([ServerError]?.self, forKey: .serverErrors)
    }

您可以这样尝试:

let container = try decoder.container(keyedBy: CodingKeys.self)
let dateString = try container.decode(String.self, forKey: .memberDateOfBirth)
let formatter = "Your Date Formatter"
if let date = formatter.date(from: dateString) {
    memberDateOfBirth = date
}
如果您想了解更多信息,请检查此方法:

对于
Dateformatter
,您可以检查:


您应该在
会员
中处理此问题,而不是
折扣
,因为每个
可编码
类型都必须能够独立解码

首先,将其添加到
折扣中
,以便仅解码名称:

enum CodingKeys : CodingKey {
    case discountName
}
然后在
成员中执行自定义解码:

enum CodingKeys: CodingKey {
    case dateOfBirth, discounts
}

public init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    dateOfBirth = try container.decode(Date.self, forKey: .dateOfBirth)
    discounts = try container.decode([Discount].self, forKey: .discounts)

    for i in 0..<discounts!.count {
        discounts![i].memberDateOfBirth = dateOfBirth
    }
}

折扣的memberDateOfBirth在折扣的JSON中不可用,我正在尝试使用成员的dateOfBirth设置它,我还需要覆盖init for折扣,因为代码中未显示其他自定义。折扣JSON没有memberDateOfBirth,因此我无法使用编码键映射它,我想使用成员的dateOfBirth设置它,这是JSON树中较高的一个对象。对不起,我以为你想解码日期@清扫者回答得很好,你可以很容易做到。谢谢@Sweeper。坦率地说,这将是未来项目的设计考虑因素,因为一般来说,JSON树中较高级别对象的属性应该由生成JSON的逻辑传播,而不需要客户机代码来传播(除非有令人信服的理由这样做)因为这可能会产生成本,例如在本例中,生成一个循环来创建集合,而不是让可编码框架来完成。再次感谢。
var discountType: String? {
    if let dob = memberDateOfBirth {
        if dob < Date(timeIntervalSince1970: 0) {
            return "Type 1"
        }
    }
    return "Type 2"
}

// or

var memberDateOfBirth: Date? {
    didSet {
        if let dob = memberDateOfBirth {
            if dob < Date(timeIntervalSince1970: 0) {
                discountType = "Type 1"
            }
        }
        discountType = "Type 2"
    }
}