我正在使用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如何正确地创建子类(此类的子类,继承)类?
我会感谢任何帮助或建议.
我正在我的 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) 我正在尝试向我的本地服务器写一个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) 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)
我在这里是正确的路线还是有更好的方法?
我有一个我想重用的函数,并让它接受一个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) 我有一个带有 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) 假设我有以下可解码结构作为示例来说明我正在尝试执行的操作:
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) 在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':
根据我的后端应用程序的设计,该字段uid是一个唯一的数字。
所以我试图通过将其类型从Intto更改来修复编译错误ObjectIdentifier,但 Swift 编译器仍然对新错误不满意Type 'Top' does not conform to protocol 'Decodable'
这里发生了什么,编译器现在可能缺少uid用于解码 JSON …
这是我的代码:
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 设为非可选并且它只有默认值?我知道我可以为此创建一个自定义解析器,但我有大量这样的请求,它需要太多的额外工作。
我正在使用可文档协议,但遇到此错误:
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) decodable ×10
swift ×7
codable ×4
json ×4
swift4 ×4
encodable ×2
ios ×2
struct ×2
identifiable ×1
inheritance ×1
swiftui ×1
swiftui-list ×1