iOS 从后台通知返回 json 数据,类型为[AnyHashable : Any]. 有什么方法可以将其解析为实现 Codable 协议的结构吗?
例子 :
// Server sends the following data via apn
{"items": [{"id": "192e7926-7891-44eb-8ca7-f795d8552e84", "text": "some text", "num": 0.7}]}
Run Code Online (Sandbox Code Playgroud)
eapp端接收数据时
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
print(userInfo["items"])
}
Run Code Online (Sandbox Code Playgroud)
print 语句给出以下输出
Optional(<__NSSingleObjectArrayI 0x283fe80b0>(
{
id = "192e7926-7891-44eb-8ca7-f795d8552e84";
num = "0.7";
text = "Check test";
}
))
Run Code Online (Sandbox Code Playgroud)
我已经有一个匹配的可编码结构:
struct Item: Codable {
let id: UUID
let text: String
let num: Double
} …Run Code Online (Sandbox Code Playgroud) 我正在使用一个类来解码检索到的 firestore 文档,如果我不想操作数据,它会按预期工作:
class Room: Identifiable, Codable {
@DocumentID public var id:String?
var name:String
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试使用自己的 init 来设置值,我无法获取 firestore 文档 ID?
class Room: Identifiable, Codable {
@DocumentID public var id:String?
var name:String
enum Keys:String, CodingKey {
case name
case capacity
case photo = "url"
}
required init(from decoder: Decoder) throws {
// How do I get the document ID to set the id value?
let container = try decoder.container(keyedBy: Keys.self)
name = try container.decode(String.self, forKey: .name)
capacity = try container.decode(Int.self, …Run Code Online (Sandbox Code Playgroud) 我想将available带有renamed和参数的属性应用于符合 的unavailable属性,如下所示:structCodable
struct SampleData: Codable {
@available(*, unavailable, renamed: "newProperty")
let oldProperty: String
let newProperty: String
}
Run Code Online (Sandbox Code Playgroud)
但是当我尝试构建此代码时,出现如下编译错误:
注意:“oldProperty”已在此处明确标记为不可用
如果 astruct不符合Codable,则效果很好。
有谁知道如何解决这个问题?
如果无法解决此问题,请告诉我原因,我将不胜感激。
提前致谢。
我们可以使 Codable 键大小写不敏感吗?不是值,但键本身需要不区分大小写
struct Model: Codable, Equatable {
let number: String?
let id: String?
let address: String?
enum CodingKeys: String, CodingKey {
case number = "A-Number"
case id = "A-Id"
case address = "AddressId"
}
}
Run Code Online (Sandbox Code Playgroud)
这样它就适用于 json:
Sample Json 1
{
"A-Number" : "12345",
"A-Id" : "1",
"AddressId" : "3456"
}
Sample Json 2
{
"a-number" : "12345",
"a-id" : "1",
"addressid" : "3456"
}
Run Code Online (Sandbox Code Playgroud) 我正在开发一个简单的音乐音序器应用程序。这种应用程序倾向于具有必须保存/加载的复杂数据结构,因此Codable在Swift4中引入协议对我来说是个好消息。
我的问题是:我必须有一个非编码属性。它不必进行编码,因为它是一个临时变量,仅在应用程序处于活动状态时才保持活动状态。因此,我只是尝试通过实现来排除CodingKey,但编译器仍然给我错误“类型'Song'不符合协议'Decodable'”。
具体来说,我想在下面的代码中排除“ musicSequence”。
class Song : Codable { //Type 'Song' does not conform to protocol 'Decodable'
var songName : String = "";
var tempo : Double = 120;
// Musical structure
var tracks : [Track] = [] // "Track" is my custom class, which conforms Codable as well
// Tones
var tones = [Int : ToneSettings] (); // ToneSettings is also my custom Codable class
var musicSequence : MusicSequence? = nil; // I get the …Run Code Online (Sandbox Code Playgroud) let jsonString = """
{
"name":1,
"gender":"male",
}
"""
struct Person: Codable {
var name: String
var gender: String
public init(from decoder: Decoder) throws {
do {
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
gender = try container.decode(String.self, forKey: .gender)
} catch {
print("XXXXXX \(error)")
}
}
}
Run Code Online (Sandbox Code Playgroud)
从上面的代码,它不会编译,因为它抱怨,
从初始化程序返回而不初始化所有存储的属性.
我想抛出一些错误,但如果没有,我该怎么办呢
Swift 4中引入了Codable。我的项目语言版本是Swift 3.3,但我仍然可以在项目中使用Codable。这不是问题,但是怎么可能呢?我只是想知道。
我建立了一组API函数,这些函数对一个对象进行编码(使用Struct符合的Codable),然后将生成的JSON Data对象发布到服务器,然后对JSON响应进行解码。一切正常-对Swift 4.2中的JSON解析新方法特别满意。但是,现在我想重构代码,以便可以将代码重用于各种方法调用-当我这样做时,我会得到一个非常烦人的错误。
func encodeRequestJSON(apiRequestObject: Codable) -> Data {
do {
let encoder = JSONEncoder()
let jsonData = try encoder.encode(apiRequestObject)
let jsonString = String(data: jsonData, encoding: .utf8)
print(jsonString)
} catch {
print("Unexpected error")
}
return jsonData!
}
Run Code Online (Sandbox Code Playgroud)
这是错误消息:
Cannot invoke 'encode' with an argument list of type '(Codable)'
Run Code Online (Sandbox Code Playgroud)
我尝试将类型从Codable更改为Encodable,但是除了消息中的类型为(Encodable)以外,发生了相同的错误。有什么建议吗?我的后备方法是在当前ViewController中对数据进行编码,然后调用HTTPPost函数,然后在VC中进行解码。但这确实很笨拙。
在您回答之前:
我意识到:
URL Employeeurl为String我正在寻找一种更好的解决方案,用于解码可选项URL本身。我希望Codable我缺少一些魔法!
所以,我有JSON之类的
let json = Data("""
{
"name": "Fred",
"url": ""
}
""".utf8)
Run Code Online (Sandbox Code Playgroud)
以及包含可选URL的相应对象…
struct Employee: Decodable {
let name: String
let url: URL?
}
Run Code Online (Sandbox Code Playgroud)
由于urlJSON中的内容无效,因此我希望将其解码为nil,而不是抛出错误。
尝试以下操作不起作用(不会被调用)…
extension Optional where Wrapped == URL {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
do {
self = try container.decode(URL.self)
} catch {
self = nil
}
}
}
Run Code Online (Sandbox Code Playgroud)
过去我用过……
struct FailableDecodable<T: …Run Code Online (Sandbox Code Playgroud) 我有一些来自服务器的JSON响应。成功的情况下,可能是这样的:
{
"success": true,
"data": [
{
/// something here
}
]
}
Run Code Online (Sandbox Code Playgroud)
如果所有服务器响应都将成功,那么解析该JSON真的很容易。但是我们也有失败案例,例如:
{
"success": false,
"msg": "Your session expired",
"end_session": true
}
Run Code Online (Sandbox Code Playgroud)
这意味着我们需要处理两种情况。如您所注意到的,类似的属性success, msg可能出现在任何响应中。为了解决这个问题,我创建了以下结构:
struct RegularResponse<T: Codable>: Codable {
let success: Bool
let msg: String?
let endSession: Bool?
let data: T?
enum CodingKeys: String, CodingKey {
case success, msg, data
case endSession = "end_session"
}
}
Run Code Online (Sandbox Code Playgroud)
如果响应成功或不成功,它可能包含一些数据,可以识别出发生错误的原因(使用successattribute或msg)。解析过程如下:
let model = try JSONDecoder().decode(RegularResponse<MyModel>.self, from: data)
if model.success {
// do something with data …Run Code Online (Sandbox Code Playgroud)