我已经在我的iOS应用程序中使用Obj-C编写的AFNetworking架构设置.它将响应作为字典返回,但我想玩一个纯JSON响应来尝试Swift 4中的Codable.这可能吗?或者我的选择是什么?
我已经定义了一个这样的枚举:
enum ClubLevel: Int, Codable {
case golden = 1, silver, bronze
}
Run Code Online (Sandbox Code Playgroud)
在我的结构中,我有一个type的可选属性,ClubLevel当我在中解码该属性时init(from decoder: Decoder):
self.clubLevel = try container.decode(ClubLevel?.self, forKey: .clubLevel)
Run Code Online (Sandbox Code Playgroud)
我遇到这个错误:
debug描述: "Cannot initialize ClubLevel from invalid Int value 0", underlyingError: nil"
我想知道即使这个属性是可选的,解码器也不会继续
任何的想法?
我有几个可编码的结构,我想创建一个通用协议,将它们编码为CKRecord for CloudKit并进行解码.
我有一个Encodable的扩展来创建一个字典:
extension Encodable {
var dictionary: [String: Any] {
return (try? JSONSerialization.jsonObject(with: JSONEncoder().encode(self), options: .allowFragments)) as? [String: Any] ?? [:]
}
}
Run Code Online (Sandbox Code Playgroud)
然后在协议扩展中,我将记录创建为属性,如果类型为Data,我尝试创建CKAsset.
var ckEncoded: CKRecord? {
// Convert self.id to CKRecord.name (CKRecordID)
guard let idString = self.id?.uuidString else { return nil }
let record = CKRecord(recordType: Self.entityType.rawValue,
recordID: CKRecordID(recordName: idString))
self.dictionary.forEach {
if let data = $0.value as? Data {
if let asset: CKAsset = try? ckAsset(from: data, id: idString) { record[$0.key] = asset }
} …Run Code Online (Sandbox Code Playgroud) 我想用 JSONEncoder 将字典编码为 json。它看起来像一个请求,接收一个字典作为参数并将其编码为 json 作为 http 正文。代码如下所示:
let dict = ["name": "abcde"]
protocol Request {
var params: [String: Encodable] { get set }
func encode<T>(_ value: T) throws -> Data where T : Encodable
}
extension Request {
func encode<T>(_ value: T) throws -> Data where T : Encodable {
return try JSONEncoder().encode(value)
}
var body: Data? {
if let encoded = try? self.encode(self.params) {
return encoded
}
return nil
}
}
struct BaseRequest: Request {
var params: [String …Run Code Online (Sandbox Code Playgroud) 我的应用程序使用一个返回 JSON 的服务器,如下所示:
{
"result":"OK",
"data":{
// Common to all URLs
"user": {
"name":"John Smith" // ETC...
},
// Different for each URL
"data_for_this_url":0
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,特定于 URL 的信息与通用user词典存在于同一词典中。
目标:
user很常见,我希望它位于顶级类/结构中。data从顶级user信息和子对象的信息重新创建字典)问题:
重新编码数据时,我无法将user字典(来自顶级对象)和特定于 URL 的数据(来自子对象)写入编码器。
要么user覆盖其他数据,要么其他数据覆盖user. 我不知道如何将它们结合起来。
这是我到目前为止所拥有的:
// MARK: - Common User
struct User: Codable {
var name: String?
}
// MARK: - Abstract Response
struct ApiResponse<DataType: Codable>: Codable …Run Code Online (Sandbox Code Playgroud) 我有一种情况,从 API 返回的 JSON 有一个名为 extension 的字段,它是 Swift 中的保留字。当我尝试使用它时,我的编码器爆炸了。
我已经搜索了过去两个小时,但似乎找不到任何解决方案。
有没有人遇到过这个:
public struct PhoneNumber: Codable {
var phoneNumber: String
var extension: String
var isPrimary: Bool
var usageType: Int
}
Run Code Online (Sandbox Code Playgroud)
关键字“extension”不能用作此处的标识符
我从API收到一个JSON响应,如下所示:
先前的JSON响应:
[
{
"EmployeeId": 711,
"FirstName": "Steve",
"LastName": "Jobs"
},
{
"EmployeeId": 714,
"FirstName": "John",
"LastName": "Doe"
}
]
Run Code Online (Sandbox Code Playgroud)
和相同的模型类具有以下代码
class EmployeeModel: Codable {
let EmployeeId: Int?
let FirstName: String?
let LastName: String?
}
Run Code Online (Sandbox Code Playgroud)
与Swift Codable解析工作正常
do {
let decodedResponse = try JSONDecoder().decode([EmployeeModel].self, from: response.rawData())
print(decodedResponse)
} catch let jsonErr {
print(jsonErr.localizedDescription)
}
Run Code Online (Sandbox Code Playgroud)
但是现在
最新的JSON响应
从API更改,并添加了一个MiddleName键作为响应,请参见以下屏幕截图,并且它与Swift Codable代码也可以正常工作。

但是,如何从iOS Swift 5的API的JSON响应中获得通知或打印MiddleName密钥的信息呢?
更新问题
根据@ CZ54在下面提供的答案,解决方案可以正常工作,但无法检查是否缺少另一个派生类。例如:
// MARK:- LoginModel
class LoginModel: Codable {
let token: String?
let …Run Code Online (Sandbox Code Playgroud) struct TestEnc: Codable {
var date = Date()
}
let encoder = JSONEncoder()
let tenc = TestEnc()
let jsonData = try encoder.encode(tenc)
let json = String(data: jsonData, encoding: String.Encoding.utf8)
print("json:\(json)")
Run Code Online (Sandbox Code Playgroud)
这打印:
json:Optional("{\"date\":589331953.61679399}")
Run Code Online (Sandbox Code Playgroud)
我在文档中找不到这应该代表什么。
我有一个 JSON,它由一个顶级对象组成,然后是一个由不同 JSON 对象组成的数组。我想用最少的结构和没有可选变量来解码这个 json。如果我可以实现,我还想设计一个结构,通过只编写其相关结构来处理所有数组对象。
我会尽量简化这个例子
正如您在图像中看到的,“Id”、“Token”、“ServicePublicKey”都是不同的 JSON 对象。我的整个后端都以这种 JSON 架构返回。我想要实现的是一个结构作为包装器和结构(Id、ServicePublicKey、Token 等)。最后,当有来自 JSON 的新类型时,我只需要编写相关的结构并在包装器中添加一些代码。
我的问题是:如何在没有任何可选变量的情况下解析这个 JSON?
我如何尝试解析它:
struct Initialization: Decodable {
var error: BunqError? //TODO: Change this type to a right one
var id: Int?
var publicKey: String?
var token: Token?
enum CodingKeys: String, CodingKey {
case error = "Error"
case data = "Response"
case Id = "Id"
case id = "id"
case ServerPublicKey = "ServerPublicKey"
case Token = "Token"
}
init(from decoder: Decoder) throws {
let …Run Code Online (Sandbox Code Playgroud) 我正在尝试解码来自第三方 API 的 JSON 响应,其中包含已进行 base64 编码的嵌套/子 JSON。
人为的示例 JSON
{
"id": 1234,
"attributes": "eyAibmFtZSI6ICJzb21lLXZhbHVlIiB9",
}
Run Code Online (Sandbox Code Playgroud)
PS"eyAibmFtZSI6ICJzb21lLXZhbHVlIiB9"是 { 'name': 'some-value' }base64 编码的。
我目前有一些代码可以对此进行解码,但不幸JSONDecoder()的是init,为了这样做,我必须重新实例化一个额外的内部,这并不酷......
人为的示例代码
struct Attributes: Decodable {
let name: String
}
struct Model: Decodable {
let id: Int64
let attributes: Attributes
private enum CodingKeys: String, CodingKey {
case id
case attributes
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(Int64.self, forKey: .id)
let encodedAttributesString = …Run Code Online (Sandbox Code Playgroud) codable ×10
swift ×9
ios ×5
json ×4
decodable ×3
encodable ×2
jsonencoder ×2
afnetworking ×1
cloudkit ×1
dictionary ×1
swift4 ×1