标签: codable

如何在Swift 4中实现JSON数据的多态解码?

我正在尝试从API端点返回的数据呈现视图。我的JSON看起来(大致)如下:

{
  "sections": [
    {
      "title": "Featured",
      "section_layout_type": "featured_panels",
      "section_items": [
        {
          "item_type": "foo",
          "id": 3,
          "title": "Bisbee1",
          "audio_url": "http://example.com/foo1.mp3",
          "feature_image_url" : "http://example.com/feature1.jpg"
        },
        {
          "item_type": "bar",
          "id": 4,
          "title": "Mortar8",
          "video_url": "http://example.com/video.mp4",
          "director" : "John Smith",
          "feature_image_url" : "http://example.com/feature2.jpg"
        }
      ]
    }    
  ]
}
Run Code Online (Sandbox Code Playgroud)

我有一个对象,表示如何在我的UI中布局视图。看起来像这样:

public struct ViewLayoutSection : Codable {
    var title: String = ""
    var sectionLayoutType: String
    var sectionItems: [ViewLayoutSectionItemable] = []
}
Run Code Online (Sandbox Code Playgroud)

ViewLayoutSectionItemable 是一种协议,其中包括要在布局中使用的图像的标题和URL。

但是,sectionItems数组实际上由不同的类型组成。我想做的是将每个小节实例化为自己类的实例。

如何设置的init(from decoder: Decoder)方法,ViewLayoutSection以便让我遍历该JSON数组中的项目并在每种情况下创建适当的类的实例?

json swift codable

9
推荐指数
3
解决办法
1494
查看次数

Swift 4 Decodable:给定数据无效JSON

我正在尝试向我的本地服务器写一个POST请求,这是我的功能:

@IBAction func postButtonAction(_ sender: UIButton) {

    guard let url = URL(string:"http://localhost:443/api/message") else {return}
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    print("POSTED")

    let date : Date = Date()
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
    let dateTime = dateFormatter.string(from: date)

    let newPost = MessageForPost(message: "Hi", timestamp: dateTime, latitude: "1.1", longitude: "2.2")
    let newData = DataForPost(message: newPost)
    let newPackage = PackageForPost(data: newData)

    do {
        let jsonBody = try JSONEncoder().encode(newPackage)
        request.httpBody = jsonBody
        print("jsonBody:",jsonBody)
        let jsonBodyString = …
Run Code Online (Sandbox Code Playgroud)

json ios swift codable decodable

9
推荐指数
1
解决办法
9922
查看次数

Swift 4 Codable:将JSON返回String转换为Int/Date/Float

我会通过一些项目和消除JSON解析框架,因为它看起来很简单斯威夫特与4.做我以前遇到过这个地方古怪JSON回报Ints,并Dates作为返回Strings.

我看着GrokSwift的JSON解析斯威夫特4,苹果公司的网站上,但我没有看到任何跳出来回复:改变类型.

Apple的示例代码显示了如何更改密钥名称,但我很难弄清楚如何更改密钥类型.

这是它的样子:

{
    "WaitTimes": [
        {
            "CheckpointIndex": "1",
            "WaitTime": "1",
            "Created_Datetime": "10/17/2017 6:57:29 PM"
        },
        {
            "CheckpointIndex": "2",
            "WaitTime": "6",
            "Created_Datetime": "10/12/2017 12:28:47 PM"
        },
        {
            "CheckpointIndex": "0",
            "WaitTime": "8",
            "Created_Datetime": "9/26/2017 5:04:42 AM"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

我曾经习惯CodingKey将字典键重命名为符合Swift的条目,如下所示:

struct WaitTimeContainer: Codable {
  let waitTimes: [WaitTime]

  private enum CodingKeys: String, CodingKey {
    case waitTimes = "WaitTimes"
  }

  struct WaitTime: Codable {
    let checkpointIndex: String
    let waitTime: …
Run Code Online (Sandbox Code Playgroud)

json ios swift swift4 codable

9
推荐指数
1
解决办法
4757
查看次数

Swift 4 JSONEncoder 中的字典键顺序

是否可以将 Swift JSON 编码器配置为使用结构体属性的排序顺序作为 JSON 输出中字典键的排序顺序?默认情况下,它使用一些任意(但看似不是随机)的顺序,例如......

struct Example: Codable {
  let id: Int
  let name: String
  let createdAt: Date
  let comments: [String]
}
Run Code Online (Sandbox Code Playgroud)

... 结果是 ...

"example" : {
  "id" : 1,
  "name" : "Test",
  "comments" : [
    "Comment 1",
    "Comment 2"
  ],
  "createdAt" : 549539643.25327206
}
Run Code Online (Sandbox Code Playgroud)

我知道从语义上来说顺序并不重要,但我想保留它以用于调试目的。

json swift codable

9
推荐指数
1
解决办法
3648
查看次数

如何使用数据和Codable优化Swift中NSAttributedString的存储?

我正在尝试在保存a的内容时优化存储空间NSTextView,即其NSTextStorage属性本身a NSAttributedString.

将其保存为Data,例如使用该rtfd(from:documentAttributes:)方法,并作为Codable结构的一部分,会产生非常大的字符串,比内容本身大得多,尤其是在将图像插入到内容中时NSTextView.例如,插入200K图像将生成5MB的JSON文件.

旁注:当Data对象直接编码而不是编码对象的属性时更糟糕,因为它是以小整数数组的形式编码而不是任意字符串.我不知道为什么,虽然我能够通过插入Data一个简单的包装结构来防止这种情况.

奇怪的是,使用ZIP压缩实际的JSON文件仍然会产生4MB的文件,只有20%的增益,因此我不清楚200K图像如何变成如此庞大,难以压缩的编码字符串.

我想弄清楚NSAttributedString使用Codable协议有效存储的正确方法是什么.非常感谢任何提示或建议.

我也想知道是否有一个有效的二进制编码选项Codable.

swift codable

9
推荐指数
1
解决办法
268
查看次数

使协议可编码并将其存储在数组中

我有一个带有 2 个符合它的结构的 Animal 协议和一个存储动物列表的 Farm 结构。然后,我让它们都符合 Codable 将其存储在一个文件中,但它抛出了错误cannot automatically synthesize 'Encodable' because '[Animal]' does not conform to 'Encodable'

我明白为什么会发生这种情况,但我找不到好的解决方案。我怎样才能让数组只接受 Codable 和 Animal,而不将 Animal 标记为 Codable 所以这个问题不会发生,比如var animals = [Codable & Animal]?(或任何其他变通方法)。谢谢

protocol Animal: Codable {
    var name: String { get set }
    var sound: String { get set }
}

struct Cow: Animal {
    var name = "Cow"
    var sound = "Moo!"
}

struct Duck: Animal {
    var name = "Duck"
    var sound = "Quack!"
} …
Run Code Online (Sandbox Code Playgroud)

swift codable decodable encodable

8
推荐指数
1
解决办法
2282
查看次数

Swift 4 Codable - API 有时提供 Int,有时提供 String

我现在正在运行 Codables。但 API 有一些字符串条目,如果它们为空,有时可能会出现Int值。0我在这里搜索并发现了这个:Swift 4 Codable - Bool or String Values但我无法让它运行

我的结构

struct check : Codable {
    let test : Int
    let rating : String?  
}
Run Code Online (Sandbox Code Playgroud)

评级大多数时候是这样的"1Star"。但如果没有评级,我会0以 Int 的身份返回。

我正在这样解析数据:

enum Result<Value> {
    case success(Value)
    case failure(Error)
}

func checkStar(for userId: Int, completion: ((Result<check>) -> Void)?) {
    var urlComponents = URLComponents()
    urlComponents.scheme = "https"
    urlComponents.host = "xyz.com"
    urlComponents.path = "/api/stars"
    let userIdItem = URLQueryItem(name: "userId", value: "\(userId)")
    urlComponents.queryItems = [userIdItem] …
Run Code Online (Sandbox Code Playgroud)

api swift swift4 codable

8
推荐指数
1
解决办法
2361
查看次数

具有多个键和关联值的可编码枚举

我已经看到有关如何在所有案例都有关联值时使枚举符合 Codable 的答案,但我不清楚如何混合具有和不具有关联值的案例的枚举:

???如何在给定情况下使用相同密钥的多个变体?

???如何编码/解码没有关联值的案例?

enum EmployeeClassification : Codable, Equatable {

case aaa
case bbb
case ccc(Int) // (year)

init?(rawValue: String?) {
    guard let val = rawValue?.lowercased() else {
        return nil
    }
    switch val {
        case "aaa", "a":
            self = .aaa
        case "bbb":
            self = .bbb
        case "ccc":
            self = .ccc(0)
        default: return nil
    }
}

// Codable
private enum CodingKeys: String, CodingKey {
    case aaa // ??? how can I accept "aaa", "AAA", and "a"?
    case bbb
    case ccc …
Run Code Online (Sandbox Code Playgroud)

enums swift codable

8
推荐指数
1
解决办法
2284
查看次数

为什么为某些属性定义 CodingKeys 需要初始化程序?

编译正常,没有问题:

class User: Codable {
    let name: String
    let email: String
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我们有一个不由 CodingKey 表示的属性,则它需要一个初始值设定项:

class User: Codable { // Class 'User' has no initializers
    let name: String
    let email: String

    private enum CodingKeys: String, CodingKey {
        case name = "username"
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么它认为问题是缺乏合成初始化器,而不是需要 CodingKey 的警告或错误?为什么这违反了 Decodable 的一致性?

编辑:由于有些人似乎很困惑,我不是问如何解决该错误。这是显而易见的。我问的是,当您没有为所需属性指定 CodingKey 时,Codable 协议中会发生什么。

ios swift codable

8
推荐指数
1
解决办法
740
查看次数

是否有可能使“任何协议”符合 Codable?

我正在尝试在 Swift 5.7 中创建一个Codable结构体[any Protocol]

struct Account: Codable {
    var id: String
    var name: String
    var wallets: [any Wallet]
}

protocol Wallet: Codable {
    var id: String { get set }
    //... other codable properties
}
Run Code Online (Sandbox Code Playgroud)

但是,即使Wallet符合Codable

类型“帐户”不符合协议“可解码”

类型“帐户”不符合协议“可编码”

是否可以做出any符合Codable

或者 Swift 5.7 仍然无法做到这一点?

编辑正如回答的那样,您必须实现自己的一致性。这就是我的做法:

protocol Wallet: Identifiable, Codable {
    var id: String { get set }
}

struct DigitalWallet: Wallet {
    var id: String
    // other properties …
Run Code Online (Sandbox Code Playgroud)

swift swift-protocols codable

8
推荐指数
1
解决办法
2262
查看次数

标签 统计

codable ×10

swift ×10

json ×4

ios ×3

decodable ×2

swift4 ×2

api ×1

encodable ×1

enums ×1

swift-protocols ×1