标签: decodable

可编码类的继承

我正在使用Swift 4和Xcode 9.2编写程序.我在编写可编码类(完全是类,而不是struct)时遇到了困难.当我尝试从另一个类继承一个类时,JSONEncoder不从子类(子)获取所有属性.请看这个:

class BasicData: Encodable {

    let a: String
    let b: String

    init() {
        a = "a"
        b = "b"
    }
}

class AdditionalData: BasicData {

    let c: String

    init(c: String) {
        self.c = c
    }

}

let encode = AdditionalData(c: "c")

do {
    let data = try JSONEncoder().encode(encode)
    let string = String(data: data, encoding: .utf8)
    if let string = string {
        print(string)
    }
} catch {
}
Run Code Online (Sandbox Code Playgroud)

它会打印出来: {"a":"a","b":"b"}

但我需要这个: {"a":"a","b":"b","c":"c"}

它看起来像c类的属性AdditionalData只是失去了某处,不知何故.

所以问题是:如果我有使用协议编码的类Encodable如何正确地创建子类(此类的子类,继承)类?

我会感谢任何帮助或建议.

inheritance swift4 codable decodable encodable

11
推荐指数
1
解决办法
1599
查看次数

Swift 4 Decodable - 没有与键 CodingKeys 关联的值

我正在我的 Swift 应用程序中解码 JSON 响应,并且代码过去一直有效,直到它决定停止工作。

这是我的 json reposnse

{
    "foods": [
        {
            "food_name": "Milk Chocolate",
            "brand_name": "Snickers",
            "serving_weight_grams": 41.7,
            "nf_calories": 212.3,
            "nf_total_fat": 11.6,
            "nf_saturated_fat": 4,
            "nf_total_carbohydrate": 22.7,
            "nf_protein": 3.9
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

这是解码我的json的代码

let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
        guard let data = data else { return }
        
        print(String(data: data, encoding: .utf8)!)
        do {
            //Decode dataResponse received from a network request
            let decoder = JSONDecoder()
            let foods = try decoder.decode(JSONFoods.self, from: data) //Decode JSON Response Data …
Run Code Online (Sandbox Code Playgroud)

json swift decodable

10
推荐指数
1
解决办法
2万
查看次数

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 JSON解码

Decodable当要解码的类型在运行时知道时,Swift 4中的协议是否可以解码JSON对象?

我有一个String类别的注册表,它将标识符映射到我们要解码的类型,如下所示:

import Foundation

struct Person: Decodable {
    let forename: String
    let surname: String
}

struct Company: Decodable {
    let officeCount: Int
    let people: [Person]
}

let registry: [String:Decodable.Type] = [
    "Person": Person.self,
    "Company": Company.self
]

let exampleJSON = """
{
    "forename": "Bob",
    "surname": "Jones"
}
""".data(using: .utf8)!

let t = registry["Person"]!

try! JSONDecoder().decode(t, from: exampleJSON) // doesn't work :-(
Run Code Online (Sandbox Code Playgroud)

我在这里是正确的路线还是有更好的方法?

json swift swift-protocols swift4 decodable

8
推荐指数
2
解决办法
942
查看次数

如何在Swift 4中引用通用的Decodable结构

我有一个我想重用的函数,并让它接受一个Decocable结构的参数.例如,这是我当前代码的简化(假设"MyDecodableStruct"是在应用程序的其他地方声明的可解码结构):

 static func getResults(url: String, parameters: Parameters) {
    // On success REST response
     if response.result.isSuccess {
        struct Results: Decodable {
          let items: [MyDecodableStruct]
         }

      if let jsonResults = try? JSONDecoder().decode(Results.self, from: response.data!) {
        //success
    }
}
Run Code Online (Sandbox Code Playgroud)

而不是说"MyDecodableStruct",我希望它是我作为参数传递的任何Decodable结构.像这样的东西:

 static func getResults(url: String, parameters: Parameters, myStruct: Decodable) {
    // On success REST response
     if response.result.isSuccess {
        struct Results: Decodable {
          let items: [myStruct]
         }

      if let jsonResults = try? JSONDecoder().decode(Results.self, from: response.data!) {
        //success
    }
}
Run Code Online (Sandbox Code Playgroud)

我会称之为

 getResults(url: "url", parameters: nil, myStruct: …
Run Code Online (Sandbox Code Playgroud)

struct swift4 decodable

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

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

我有一个带有 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
查看次数

无需 CodingKeys 的 Swift 自定义可解码初始值设定项

假设我有以下可解码结构作为示例来说明我正在尝试执行的操作:

struct Object: Decodable {
    var id: String
    var name: String
}
Run Code Online (Sandbox Code Playgroud)

和这个 JSON:

[
    {
        "id": "a",
        "name": "test"
    },
    {
        "id": "b",
        "name": null
    }
]
Run Code Online (Sandbox Code Playgroud)

请注意,名称属性null有时可能是。这基本上可以正常工作,因为 json 键与结构属性名称匹配,所以我不需要枚举CodingKey,但name属性有时可以为 null。但是,name我不想将其设置为可选,而是想替换默认字符串,因此我需要一个自定义初始值设定项:

struct Object: Decodable {
    var id: String
    var name: String

    init(from decoder: Decoder) throws {
        ...
        self.name = <value from decoder> ?? "default name"
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

但这需要一个CodingKey对象。我正在使用默认键。我CodingKey现在还需要一个枚举吗?即使我所有的钥匙都匹配?或者有没有一种方法可以Decodable只使用键本身来自定义初始化程序?

是否有某种我可以使用的默认容器?

let container = try decoder.container(keyedBy: …
Run Code Online (Sandbox Code Playgroud)

swift decodable

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

如何使我的结构可识别?它有一个唯一的数字 uid 字段

Github 的一个简单项目中,我尝试下载 JSON 对象列表:

struct TopResponse: Codable {
    let data: [Top]
}

struct Top: Codable /*, Identifiable */ {
    let uid: Int
    let elo: Int
    let given: String
    let photo: String?
    let motto: String?
    let avg_score: Double?
    let avg_time: String?
}
Run Code Online (Sandbox Code Playgroud)

这效果很好,下一步我想将它显示在 SwiftUI 列表中,从而添加Identifiable到结构中。

不幸的是,这会产生编译错误Type 'Top' does not conform to protocol 'Identifiable'

错误1

根据我的后端应用程序的设计,该字段uid是一个唯一的数字。

所以我试图通过将其类型从Intto更改来修复编译错误ObjectIdentifier,但 Swift 编译器仍然对新错误不满意Type 'Top' does not conform to protocol 'Decodable'

错误2

这里发生了什么,编译器现在可能缺少uid用于解码 JSON …

swift decodable swiftui swiftui-list identifiable

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

Swift Codable 将空 json 解码为 nil 或空对象

这是我的代码:

class LoginUserResponse : Codable {
    var result: String = ""
    var data: LoginUserResponseData?
    var mess: [String] = []
}

public class LoginUserResponseData : Codable {
    var userId = "0"
    var name = ""
}
Run Code Online (Sandbox Code Playgroud)

现在,调用服务器 API 我正在解析这样的响应(使用 Stuff 库来简化解析):

do {
    let loginUserResponse = try LoginUserResponse(json: string)
} catch let error {
    print(error)
}
Run Code Online (Sandbox Code Playgroud)

当我输入正确的密码时,我会得到这样的答案:

{"result":"success","data":{"userId":"10","name":"Foo"},"mess":["You're logged in"]}
Run Code Online (Sandbox Code Playgroud)

这很好,解析器工作正常。

提供错误密码时给出以下答案:

{"result":"error","data":{},"mess":["Wrong password"]}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,解析器失败了。它应该将数据设置为 nil,而是尝试将其解码为 LoginUserResponseData 对象。

我在使用改造的 Android 上使用相同的方法,它工作正常。我宁愿不想将所有字段都设为可选。

有没有办法让解析器将空的 json {} 视为 nil?或者将 LoginUserResponseData 设为非可选并且它只有默认值?我知道我可以为此创建一个自定义解析器,但我有大量这样的请求,它需要太多的额外工作。

ios swift codable decodable

7
推荐指数
2
解决办法
2万
查看次数

预期解码 Dictionary&lt;String, Any&gt; 但发现了字符串/数据

我正在使用可文档协议,但遇到此错误:

typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [MakeApp_v2.Params.(CodingKeys in _244BBB2F32A8C5CF3DB84B0C6A94B232).config, Swift._DictionaryCodingKey(stringValue: "table", intValue: nil)], debugDescription: "Expected to decode Dictionary<String, Any> but found a string/data instead.", underlyingError: nil))
Run Code Online (Sandbox Code Playgroud)

这是我遇到错误的 JSON

{
  "callBackID" : "add1867f-6005-189c-bbb4-ff53202b0697",
  "config" : {
    "description" : "Welcome Page",
    "show-bottom-bar" : "",
    "css-page-align" : "",
    "footer" : { "show" : "", "object" : "bottom-bar" },
    "pageStyle" : "full-page",
    "sourceType" : "list",
    "title" : "Welcome Page",
    "header" : { "show" : true, "hide" : false, "object" : "top-bar" },
    "columns" : {},
    "objects" …
Run Code Online (Sandbox Code Playgroud)

json struct swift4 decodable

7
推荐指数
1
解决办法
8746
查看次数