解码子级时访问嵌套 Codable 结构中父级结构的属性

2024-04-29

在嵌套中使用解码器时Codablestruct,有什么方法可以访问父结构的属性吗?

我能想到的唯一可行的方法(尚未测试)是在父结构中也使用手动解码器,在userInfo字典,然后访问userInfo在子结构中。但这会产生大量样板代码。我希望有一个更简单的解决方案。

struct Item: Decodable, Identifiable {
    let id: String
    let title: String
    let images: Images

    struct Images: Decodable {
        struct Image: Decodable, Identifiable {
            let id: String
            let width: Int
            let height: Int

            init(from decoder: Decoder) throws {
                let container = try decoder.container(keyedBy: CodingKeys.self)
                width = try container.decode(Int.self, forKey: .width)
                height = try container.decode(Int.self, forKey: .height)

                // How do I get `parent.parent.id` (`Item#id`) here?
                id = "\(parent.parent.id)\(width)\(height)"
            }
        }

        let original: Image
        let small: Image
        // …
    }
}

在上面的示例中,来自服务器的项目 ID 仅在 JSON 的顶级属性中定义,但我也需要在子级属性中定义它们,所以我也可以将它们设置为Identifiable.


我使用 @New Dev 提到的 Itai Ferber 的建议进行了管理,方式如下:

  1. 创建一个新的引用类型,其唯一目的是包含 可以在父级和子级之间传递的可变值。
  2. 将该类型的实例分配给 JSONDecoder 的 userInfo 字典。
  3. 在解码父实例时检索该实例,并将您有兴趣传递的 id 分配给它。
  4. 在解码子级时,从先前存储在 userInfo 中的实例中检索该 id。

我已将您上面的示例修改如下:

struct Item: Decodable, Identifiable {

    enum CodingKeys: String, CodingKey {
        case id
        case title
        case images
    }

    let id: String
    let title: String
    let images: Images

    struct Images: Decodable {
        struct Image: Decodable, Identifiable {
            let id: String
            let width: Int
            let height: Int

            init(from decoder: Decoder) throws {
                let container = try decoder.container(keyedBy: CodingKeys.self)
                width = try container.decode(Int.self, forKey: .width)
                height = try container.decode(Int.self, forKey: .height)

                if let referenceTypeUsedOnlyToContainAChangeableIdentifier = decoder.userInfo[.referenceTypeUsedOnlyToContainAChangeableIdentifier] as? ReferenceTypeUsedOnlyToContainAChangeableIdentifier {
                    self.id = referenceTypeUsedOnlyToContainAChangeableIdentifier.changeableIdentifier
                } else {
                    self.id = "something went wrong"
                }
            }
        }

        let original: Image
        let small: Image
        // …

        init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            id = try container.decode(String.self, forKey: .id)
            if let referenceTypeUsedOnlyToContainAChangeableIdentifier = decoder.userInfo[.referenceTypeUsedOnlyToContainAChangeableIdentifier] as? ReferenceTypeUsedOnlyToContainAChangeableIdentifier {
               referenceTypeUsedOnlyToContainAChangeableIdentifier.changeableIdentifier = id
            }
        }
    }
}

// Use this reference type to just store an id that's retrieved later.
class ReferenceTypeUsedOnlyToContainAChangeableIdentifier {
    var changeableIdentifier: String?
}

// Convenience extension.
extension CodingUserInfoKey {
    static let referenceTypeUsedOnlyToContainAChangeableIdentifier = CodingUserInfoKey(rawValue: "\(ReferenceTypeUsedOnlyToContainAChangeableIdentifier.self)")!
}

let decoder = JSONDecoder()
// Assign the reference type here to be used later during the decoding process first to assign the id in `Item` and then
// later to retrieve that value in `Images`
decoder.userInfo[.referenceTypeUsedOnlyToContainAChangeableIdentifier] = ReferenceTypeUsedOnlyToContainAChangeableIdentifier()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

解码子级时访问嵌套 Codable 结构中父级结构的属性 的相关文章

  • Swift:本地化字符串数组

    我有一个包含 100 多个字符串的数组 其设置如下所示 有什么方法可以本地化数组中的所有字符串 或者这是设置它的更好方法吗 var listOfThings Cars Mopeds 我建议将字符串放入 plist 文件中 然后可以根据需要本
  • Firebase queryOrderedbyChild 不返回 Null 值

    我有一个根据年龄搜索用户的查询 self ref child users queryOrdered byChild age queryStarting atValue 18 queryEnding atValue 25 observeSin
  • 自定义相机视图 Swift iOS 8 iPhone Xcode 6.1

    我想在 iPhone 的 View 中使用相机 我不想使用典型的全屏相机视图 而是我自己的 例如 我想在屏幕中间有一个 200x200 的正方形 并且有一个相机预览 在这个方块下面我想要一个拍照按钮 怎么做 我是新手 速度很快 你会想要使用
  • 更改iOS11中的UISearchBar背景图片

    我想更改我的 UISearchBar 背景图像 当将它添加为我的 UITableView 中的标题视图时 它工作得很好 但是 当我想更改它以将 SearchBar 设置为 navigationItem 的 searchController
  • C 中的隐秘结构定义

    我遇到了以下情况迷宫定义 https github com gduarte lkb blob master code stack maze h code typedef struct mazeNode int hasCheese int t
  • 如何在松开按钮后立即看到新的视频层?

    我有一个应用程序 用户可以按住按钮来拍摄视频 然而 当他们这样做时 带有视频播放的新图层不会立即出现 相反 有一个非常短的延迟 在用户松开按钮后 您可以看到相机仍然显示相机所看到的内容 延迟结束后 视频立即显示并开始播放 但是 我怎样才能使
  • GM 发布 Xcode 6 编译

    我刚刚下载了 Xcode 6 的 GM 版本 但无法编译并出现以下错误 Command Applications Xcode app Contents Developer Toolchains XcodeDefault xctoolchai
  • 如何在不使用 viewWillDisappear 的情况下使 NSTimer 无效/取消初始化?

    var faderTimer NSTimer override func viewDidLoad super viewDidLoad self faderTimer NSTimer scheduledTimerWithTimeInterva
  • iOS推送通知:当应用程序处于后台时,如何检测用户是否点击了通知?

    关于这个主题有很多 stackoverflow 线程 但我仍然没有找到好的解决方案 如果应用程序不在后台 我可以检查launchOptions UIApplicationLaunchOptionsRemoteNotificationKey
  • 在视图控制器中获取 applicationDidFinishLaunching 调用。解析尚未初始化

    我正在尝试从 Parse 加载数据Initial View 控制器 问题是 Parse 在我的中初始化AppDelegate s didFinishLaunching所以我需要等到它被调用后再尝试从 Parse 加载数据 在我的视图控制器中
  • UIStackView分布均匀填充

    所以 我有一个UIStackView其中包含四 4 UIViews 如果我删除其中一 1 个UIViews 其他三 3 个将填满UIStackView 我的问题 如何添加最大高度UIView这样它就不会填满整个空间UIStackView即使
  • 闭包存储属性初始化有什么好处?

    初始化类的属性时 此代码有什么区别以及优点 缺点 1 let menuBar MenuBar let mb MenuBar return mb and 2 let menuBar MenuBar 两个代码片段都声明并初始化存储的属性 htt
  • 核心数据:重命名属性,而不会导致用户及其当前数据出现问题

    我只想为我的应用程序的新版本重命名并在表上添加属性 并且如果应用程序已安装 我想保留数据 首先我只是设置选项 let options NSMigratePersistentStoresAutomaticallyOption true NSI
  • iOS - 如何在 swift 中使用 `NSMutableString`

    我已经看过这段 Objective C 代码 但我很难在 swift 中做同样的事情 NSMutableAttributedString res self richTextEditor attributedText mutableCopy
  • .showsPhysics 内存泄漏

    我最近花了 5 个小时尝试调试 Spritekit 应用程序中的内存泄漏 应用程序启动后 我注意到内存使用量略有上升 我花了 5 个小时中的 3 个小时挖掘参考资料 了解强与弱的关系ARC https developer apple com
  • 有关 Swift 编译器选项的文档

    您好 我想开始在 Apple Swift 语言上运行一些微基准测试 然而 我觉得很难找到有关编译器优化的不同选项的适当文档 我读过很多关于其他人的语言微基准的问题和文章 但是如果能有一些关于该主题的可靠文档那就太好了 在最新的测试版中 使用
  • ios swift parse:从 3 个类收集数据

    我有这样的结构 User CardSet 带有指向 User objectId 的指针 user 和 col name 带有点 cards 的卡片到 Card Set objectId 和列 name 我想选择所有卡数据 包括当前用户的卡集
  • ReactiveCocoa 将 SignalProducers 合二为一

    我正在使用 ReactiveCocoa 并且我有几个 SignalProducers let center NSNotificationCenter defaultCenter let signalProducer1 center rac
  • 根据一个数组对多个数组进行排序

    如何根据数组对一堆数组进行排序createdAt 例如 2015 11 02 19 19 35 0000 将它们组合成另一种类型 字典 以便在 tableView 中使用是否有益 如果有的话如何 var comment AnyObject
  • SpriteKit的更新函数:时间与帧率

    一般来说 我对编程和 Spritekit 很陌生 并且有兴趣探索毫秒和帧率之间的关系 以及如何使用更新函数作为两者之间的中介 帧率与毫秒 从本质上讲 帧速率和时间之间的主要区别在于时间始终一致 而帧速率则不然 由于密集的图形程序 它可能会下

随机推荐