使用Swift 4 Codable PropertyListDecoder()解码PropertyList [英] Decode PropertyList using Swift 4 Codable PropertyListDecoder()

查看:154
本文介绍了使用Swift 4 Codable PropertyListDecoder()解码PropertyList的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 PropertyListDecoder()解码plist,但是当我尝试访问密钥时,出现一个错误,提示它的格式错误。我对自己做错的事不知所措。我假设我可以解码 Plist 文件,就像解码JSON文件一样吗?我不知道,我还是新手。

  // PLists 
struct AccessControl:可解码{
枚举AccessControlKeys:字符串,CodingKey {
case api
}

枚举KeySecretKeys:字符串,CodingKey {
case apiKey = KEY
case apiSecret = SECRET
}

var KEYS:[KeySecrets]
//自定义解码器
init(来自解码器:Decoder)throw {
让accessContainer = try encoder.container(keyedBy:AccessControlKeys .self)
让nestedContainer =尝试accessContainer.nestedContainer(keyedBy:KeySecretKeys.self,forKey:.api)
self.KEYS =尝试nestedContainer([KeySecrets] .self,forKey:.apiKey)
self.KEYS =试试nestedContainer.decode([KeySecrets] .self,forKey:.apiSecret)
}
}

结构KeySecrets:可分解{
var apiKey:字符串
var api秘密:字符串
}



func ProvideAccessKeys(用于api:apis = .api,mode:modes = .dev)-> keysForApi? {
case api {
case .api:
print( Api)
}
switch mode {
case .dev:
print( mode-developers)
case .test:
print( mode-test)
case .prod:
print( mode-production)
}
}

这是我的第一种方法,但是会抛出错误提示


'由于格式错误,无法读取数据'




 如果let fileURL = Bundle.main.url(forResource: Accesscontrol,withExtension: plist){
做{
让数据=尝试Data.init(contentsOf:fileURL,选项:.mappedIfSafe)
让解码器= PropertyListDecoder()
让结果=尝试解码器.decode(AccessControl.self,来自:数据)

}捕获{
print(error.localizedDescription)
}
}

第二种方法,有点只是放弃了 Codable 在一起,仍然无法提取值

  guard let fileUrl = Bundle.main.url(forResource: Accesscontrol,withExtension: plist)else {return} 
let键:String
let secret:字符串
do {
let data = try Data.init(contentsOf:fileUrl,选项:.mappedIfSafe)
let plist = try! PropertyListSerialization.propertyList(来自:数据,选项:[],格式:无)为! [任何]
print(plist)
let词典= plist [api.rawValue]

} catch {
print(error.localizedDescription)
}

plist文件的结构类似于

 < plist version = 1.0> 
< dict>
< key> A_GROUP_OF_KEYS< / key>
< array>
< dict>
< key> KEY1< / key>
< string> KEY1_STRING< / string>
< key> SECRET1_KEY< / key>
< string> SECRET1_STRING< / string>
< / dict>
< dict>
< key> KEY2< / key>
< string> KEY2_STRING< / string>
< key> SECRET2_KEY< / key>
< string> SECRET2_VALUE< / string>
< / dict>
< dict>
< key> KEY< / key>
< string> KEY_STRING< / string>
< key> SECRET_KEY< / key>
< string> SECRET_VALUE< / string>
< / dict>
< / array>
< key> ANOTHER_GROUP_OF_KEYS< / key>
< array>
< dict>
< key> KEY1< / key>
< string> KEY1_STRING< / string>
< key> SECRET1_KEY< / key>
< string> SECRET1_STRING< / string>
< / dict>
< dict>
< key> KEY2< / key>
< string> KEY2_STRING< / string>
< key> SECRET2_KEY< / key>
< string> SECRET2_VALUE< / string>
< / dict>
< dict>
< key> KEY< / key>
< string> KEY_STRING< / string>
< key> SECRET_KEY< / key>
< string> SECRET_VALUE< / string>
< / dict>
< / array>
< / dict>
< / plist>

有什么建议吗?

解决方案

您的plist文件格式错误,因此无法解码。您不应该用不同的键名来命名每个键,例如 KEY1 KEY2 KEY3 等。相反,您应该对键 key 使用一个名称,并将实际名称放在值字段中。 秘密也是如此。



这里是一个更好的plist文件:

 <?xml version = 1.0 encoding = UTF-8?> 
<!DOCTYPE plist PUBLIC-// Apple // DTD PLIST 1.0 // EN http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
< plist version = 1.0>
< dict>
< key> A_GROUP_OF_KEYS< / key>
< array>
< dict>
< key> key< / key>
< string> KEY1_STRING< / string>
< key> secret< / key>
< string> SECRET1_STRING< / string>
< / dict>
< dict>
< key> key< / key>
< string> KEY2_STRING< / string>
< key> secret< / key>
< string> SECRET2_VALUE< / string>
< / dict>
< dict>
< key> key< / key>
< string> KEY3_STRING< / string>
< key> secret< / key>
< string> SECRET3_VALUE< / string>
< / dict>
< / array>
< key> ANOTHER_GROUP_OF_KEYS< / key>
< array>
< dict>
< key> key< / key>
< string> KEY1_STRING< / string>
< key> secret< / key>
< string> SECRET1_STRING< / string>
< / dict>
< dict>
< key> key< / key>
< string> KEY2_STRING< / string>
< key> secret< / key>
< string> SECRET2_VALUE< / string>
< / dict>
< dict>
< key> key< / key>
< string> KEY3_STRING< / string>
< key> secret< / key>
< string> SECRET3_VALUE< / string>
< / dict>
< / array>
< / dict>
< / plist>

解码非常简单:

  struct AccessControl:可解码{
struct密钥:可解码{
var键:String
var secret:String
}

var keyGroup1:[密钥]
var keyGroup2:[密钥]

枚举CodingKeys:字符串,CodingKey {
case keyGroup1 = A_GROUP_OF_KEYS
case keyGroup2 = ANOTHER_GROUP_OF_KEYS
}
}


Im trying to decode a plist using PropertyListDecoder() but when I get to the trying to access the keys, I get an error that says it's in the wrong format. I'm at a loss on what I'm doing wrong. Im under the assumption I can decode a Plist file the same way I can decode a JSON file right? I don't know, I'm still new to this.

//struct for PLists
struct AccessControl: Decodable {
    enum AccessControlKeys: String, CodingKey {
         case api
     }

    enum KeySecretKeys: String, CodingKey {
        case apiKey = "KEY"
        case apiSecret = "SECRET"
    }

    var KEYS: [KeySecrets]
//custom decoder
    init(from decoder: Decoder) throws {
        let accessContainer = try decoder.container(keyedBy: AccessControlKeys.self)
        let nestedContainer = try accessContainer.nestedContainer(keyedBy: KeySecretKeys.self, forKey: .api)
        self.KEYS = try nestedContainer([KeySecrets].self, forKey: .apiKey)
        self.KEYS = try nestedContainer.decode([KeySecrets].self, forKey: .apiSecret)
    }
}

struct KeySecrets: Decodable {
    var apiKey: String
    var apiSecret: String
}



func provideAccessKeys(for api: apis = .api, mode: modes = .dev) -> keysForApi? {
    switch api {
    case .api:
        print("Api")
    }
    switch mode {
    case .dev:
        print("mode - developers")
    case .test:
        print("mode - test")
    case .prod:
        print("mode - production")
    }
}

This was my first approach at it, but it would throw an error saying

'The data couldn't be read because it was the wrong format'

if let fileURL = Bundle.main.url(forResource: "Accesscontrol",   withExtension: "plist") {
    do {
        let data = try Data.init(contentsOf: fileURL, options: .mappedIfSafe)
        let decoder = PropertyListDecoder()
        let result = try decoder.decode(AccessControl.self, from: data)

    } catch {
        print(error.localizedDescription)
    }
}

Second approach, kinda just abandoned Codable all together, still couldn't pull out the values

guard let fileUrl = Bundle.main.url(forResource: "Accesscontrol", withExtension: "plist") else {return}
let key: String
let secret: String
do {
    let data = try Data.init(contentsOf: fileUrl, options: .mappedIfSafe)
    let plist = try! PropertyListSerialization.propertyList(from:data, options: [], format: nil) as! [Any]
  print(plist)
   let dictionary = plist[api.rawValue]

} catch {
    print(error.localizedDescription)
}

The plist file is structured like

<plist version="1.0">
<dict>
    <key>A_GROUP_OF_KEYS</key>
    <array>
        <dict>
            <key>KEY1</key>
            <string>KEY1_STRING</string>
            <key>SECRET1_KEY</key>
            <string>SECRET1_STRING</string>
        </dict>
        <dict>
        <key>KEY2</key>
        <string>KEY2_STRING</string>
        <key>SECRET2_KEY</key>
        <string>SECRET2_VALUE</string>
        </dict>
        <dict>
        <key>KEY</key>
        <string>KEY_STRING</string>
        <key>SECRET_KEY</key>
        <string>SECRET_VALUE</string>
        </dict>
    </array>
<key>ANOTHER_GROUP_OF_KEYS</key>
    <array>
        <dict>
            <key>KEY1</key>
            <string>KEY1_STRING</string>
            <key>SECRET1_KEY</key>
            <string>SECRET1_STRING</string>
        </dict>
        <dict>
        <key>KEY2</key>
        <string>KEY2_STRING</string>
        <key>SECRET2_KEY</key>
        <string>SECRET2_VALUE</string>
        </dict>
        <dict>
        <key>KEY</key>
        <string>KEY_STRING</string>
        <key>SECRET_KEY</key>
        <string>SECRET_VALUE</string>
        </dict>
    </array>
</dict>
</plist>

Any advice?

解决方案

Your plist file was badly formatted and hence undecodable. You shouldn't name every key with a different key name like KEY1, KEY2, KEY3, etc. Instead, you should use one name for the key key and put the actual name in the value field. The same goes for secret.

Here's a better plist file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>A_GROUP_OF_KEYS</key>
    <array>
        <dict>
            <key>key</key>
            <string>KEY1_STRING</string>
            <key>secret</key>
            <string>SECRET1_STRING</string>
        </dict>
        <dict>
            <key>key</key>
            <string>KEY2_STRING</string>
            <key>secret</key>
            <string>SECRET2_VALUE</string>
        </dict>
        <dict>
            <key>key</key>
            <string>KEY3_STRING</string>
            <key>secret</key>
            <string>SECRET3_VALUE</string>
        </dict>
    </array>
    <key>ANOTHER_GROUP_OF_KEYS</key>
    <array>
        <dict>
            <key>key</key>
            <string>KEY1_STRING</string>
            <key>secret</key>
            <string>SECRET1_STRING</string>
        </dict>
        <dict>
            <key>key</key>
            <string>KEY2_STRING</string>
            <key>secret</key>
            <string>SECRET2_VALUE</string>
        </dict>
        <dict>
            <key>key</key>
            <string>KEY3_STRING</string>
            <key>secret</key>
            <string>SECRET3_VALUE</string>
        </dict>
    </array>
</dict>
</plist>

Decoding this is dead simple:

struct AccessControl: Decodable {
    struct Key: Decodable {
        var key: String
        var secret: String
    }

    var keyGroup1: [Key]
    var keyGroup2: [Key]

    enum CodingKeys: String, CodingKey {
        case keyGroup1 = "A_GROUP_OF_KEYS"
        case keyGroup2 = "ANOTHER_GROUP_OF_KEYS"
    }
}

这篇关于使用Swift 4 Codable PropertyListDecoder()解码PropertyList的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆