【问题标题】:Generic Codable types通用可编码类型
【发布时间】:2021-10-08 07:42:52
【问题描述】:

我有一个想法,我正在尝试测试,我希望能够拥有一组不同的对象,这些对象都是可编码的。

这是json

{
  "cells": 
  [
    { 
      "header": "dummy header"
    },
    {
      "title": "dummy title"
    }
  ]
}

还有一张来自 Firestore 的图片,因为我不确定我是否正确地写出了那个 json:

这是迄今为止我使用泛型进行的测试

struct Submission<Cell: Codable>: Codable {
    let cells: [Cell]
}

struct ChecklistCell: Codable {
    let header: String
}

struct SegmentedCell: Codable {
    let title: String
}

首要目标是解码具有(单元格)数组的文档,该数组可以是不同的类型,但都是可编码的。我不确定这是否可能,或者是否有更好的方法。谢谢。

更新: 我做了@Fogmeister 的解决方案并让它工作,但不是最理想的结果。它为 json 添加了一个奇怪的层,理想情况下它不会存在。有什么想法吗?

【问题讨论】:

  • 你并没有真正提出问题,但让我指出任何类型都符合 Codable 如果其所有包含类型都符合 Codable
  • @JoakimDanielson 听起来你在说如果我有一个内部带有字符串类型的结构,那么该结构是自动编码的吗? "如果所有包含的类型都符合 Codable,则任何类型都符合 Codable"
  • 是的,如果你声明它符合 Codable
  • 考虑反过来考虑并发送符合Codable 的数据结构。 Swift 默认不支持异构数组。使用您的代码,您无法同时解码 ChecklistCellSegmentedCell。合成的实现仅支持同构数组。
  • @vadian 谢谢,我认为这清除了它,我觉得这是不可能的,一直跑到死胡同。

标签: json swift generics codable


【解决方案1】:

我过去做过类似的事情。不是使用 Firestore(尽管最近我这样做了),而是使用我们使用的 CMS。

正如@vadian 指出的那样,Swift 不支持异构数组。

还有...要指出的其他内容。

当你定义了一个泛型类型时...

struct Submission<Cell> {
  let cells: [Cell]
}

那么,根据定义,cells 是单一类型的同构数组。如果您尝试将不同的类型放入其中,它将无法编译。

您可以通过使用枚举将所有不同的 Cell 捆绑到一个类型中来解决此问题。

enum CellTypes {
  case checkList(CheckListCell)
  case segmented(SegmentedCell)
}

现在您的数组将是[CellTypes] 的同构数组,其中每个元素都是枚举的一个情况,然后将包含其中的单元格模型。

struct Submission {
  let cells: [CellTypes]
}

这需要一些自定义解码才能直接从 JSON 获取,但我现在无法添加。如果您需要一些指导,我会更新答案。

编码和解码

从 JSON 的角度来看需要注意的事项。您的应用需要知道正在编码/解码的单元格类型。因此,您的原始 JSON 架构需要一些更新才能添加。

您展示的从 Firestore 自动更新是一种相当常见的方式...

JSON 看起来有点像这样......

{
  "cells": 
  [
    {
      "checkListCell": { 
        "header": "dummy header"
      }
    },
    {
      "segmentedCell": {
        "title": "dummy title"
      }
    }
  ]
}

本质上,数组中的每个项目现在都是一个具有单个键的对象。来自checkListCellsegmentedCell。这将来自您的枚举的任何情况。此键告诉您的应用该对象是哪种类型的单元格。

那么针对该键显示的对象就是底层单元格本身。

这可能是对这些数据建模的最简洁的方法。

因此,您可能有两个清单单元格,然后是一个分段单元格,最后是另一个清单单元格。

这看起来像......

{
  "cells": 
  [
    {
      "checkListCell": { 
        "header": "First checklist"
      }
    },
    {
      "checkListCell": { 
        "header": "Second checklist"
      }
    },
    {
      "segmentedCell": {
        "title": "Some segmented stuff"
      }
    },
    {
      "checkListCell": { 
        "header": "Another checklist"
      }
    },
  ]
}

分析此 JSON 时要考虑的重要一点不是您(作为人类)更难阅读。但它是必需的,而且实际上相当容易,您的应用程序才能读取和解码/编码。

希望这是有道理的。

【讨论】:

  • 谢谢!没想到用不同情况的枚举,完美!
  • 如果您可以检查一下,我添加了一个更新,我想我确实需要编码和解码方面的帮助...
  • 刚刚进行更新。 :D
  • @EricE 这有点棘手,因为您的原始 JSON 结构需要更改才能使用它。因为您需要知道每个条目是哪种类型的单元格。目前没有类型信息。
猜你喜欢
  • 1970-01-01
  • 2023-03-14
  • 2021-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多