【问题标题】:Convert dictionary to query string in swift?快速将字典转换为查询字符串?
【发布时间】:2017-06-30 04:15:30
【问题描述】:

我有一个字典为[String:Any]。现在我想将此字典键和值转换为key=value&key=value。我创建了下面的扩展来工作,但它对我不起作用。

extension Dictionary {

    var queryString: String? {
        var output: String = ""
        for (key,value) in self {
            output +=  "\(key)=\(value)\(&)"
        }
        return output
    }
}

【问题讨论】:

  • Foundation 框架为此提供了 URLComponents / URLQueryItems 类。为什么queryString 是可选的?
  • 选中此stackoverflow.com/a/44824746/6433023 以从Dictionary 制作URLQueryItems 数组
  • @rmaddy 此处的所有答案在您传递嵌套字典时都会崩溃。
  • @SuhasAithal 你为什么要告诉我?这不是我的问题。没有一个答案是我的。如果您有不同的需求,请发布您自己的问题以及所有相关详细信息。甚至将这个问题作为类似但不同的需求链接。

标签: swift


【解决方案1】:

使用NSURLQueryItem

一个 NSURLQueryItem 对象代表一个单一的名称/值对 URL 的查询部分中的项目。您将查询项与 NSURLComponents 对象的 queryItems 属性。

要创建一个使用指定的初始化器queryItemWithName:value:,然后将它们添加到NSURLComponents 以生成NSURL。例如:

目标-C:

NSDictionary *queryDictionary = @{ @"q": @"ios", @"count": @"10" };
NSMutableArray *queryItems = [NSMutableArray array];
for (NSString *key in queryDictionary) {
    [queryItems addObject:[NSURLQueryItem queryItemWithName:key value:queryDictionary[key]]];
}
components.queryItems = queryItems;
NSURL *url = components.URL; // http://stackoverflow.com?q=ios&count=10

斯威夫特:

let queryDictionary = [ "q": "ios", "count": "10" ]
var components = URLComponents()
components.queryItems = queryDictionary.map {
     URLQueryItem(name: $0, value: $1)
}
let URL = components.url

【讨论】:

  • 请用 Swift 编写代码,因为问题用 Swift 标记
  • 那很好但是现在不用absoluteString直接使用url
  • 传递嵌套字典时会崩溃
【解决方案2】:

另一种 Swift 风格的方法:

let params = [
    "id": 2,
    "name": "Test"
]

let urlParams = params.flatMap({ (key, value) -> String in
    return "\(key)=\(value)"
}).joined(separator: "&")

【讨论】:

  • 感谢它在 Swift 4.2 中工作得更好但现在 .flatMap 在 Swift 4.2 中变为 .compactMap
【解决方案3】:
var populatedDictionary = ["key1": "value1", "key2": "value2"]

extension Dictionary {
    var queryString: String {
        var output: String = ""
        for (key,value) in self {
            output +=  "\(key)=\(value)&"
        }
        output = String(output.characters.dropLast())
        return output
    }
}

print(populatedDictionary.queryString)

// Output : key1=value1&key2=value2

希望对您有所帮助。快乐编码!

【讨论】:

  • 为什么不增加索引
  • 索引在这里不起作用。我刚刚从字符串中删除了最后一个字符。我已经更新了我得到的输出。这是你要求的吗??
  • 为什么要投反对票。 Ans满足了要求。我知道有很多方法可以完成相同的任务,我没有以另一种方式实现相同的任务,而是修改了@deepakkumar 现有代码以符合要求。
  • @luckyShubhra 你有没有试过运行它有一个错误的代码Use of unresolved identifier 'output',这就是为什么有人反对它,请更正它,否则其他用户也会反对它。跨度>
  • 如果您使用带有空格或“?”的值或“&”你不会得到一个带有这个查询字符串的 URL
【解决方案4】:
extension Dictionary {
    var queryString: String? {
        return self.reduce("") { "\($0!)\($1.0)=\($1.1)&" }
    }
}

【讨论】:

  • 不错,但最后留下了“&”
【解决方案5】:

与@KKRocks 相同,更新为 swift 4.1.2

func queryItems(dictionary: [String:Any]) -> String {
    var components = URLComponents()
    print(components.url!)
    components.queryItems = dictionary.map {
        URLQueryItem(name: $0, value: String(describing: $1))
    }
   return (components.url?.absoluteString)!
}

【讨论】:

    【解决方案6】:

    @luckyShubhra 答案的精简版

    Swift 5.0

    extension Dictionary {
        var queryString: String {
            var output: String = ""
            forEach({ output += "\($0.key)=\($0.value)&" })
            output = String(output.dropLast())
            return output
        }
    }
    

    用法

    let populatedDictionary = ["key1": "value1", "key2": "value2"]
    let urlQuery = populatedDictionary.queryString
    print(urlQuery)
    

    【讨论】:

    • 我认为 StringProtocol 一致性将使这更安全。即扩展字典 where Key : StringProtocol, Value : StringProtocol ...
    【解决方案7】:

    试试这个:

    func queryItems(dictionary: [String:Any]) -> String {
            var components = URLComponents()
            print(components.url!)
            components.queryItems = dictionary.map {
                URLQueryItem(name: $0, value: $1)
            }
           return (components.url?.absoluteString)!
        }
    

    【讨论】:

      【解决方案8】:
      import Foundation
      
          extension URL {
              var queryItemsDictionary: [String: String] {
                  var queryItemsDictionary = [String: String]()
      
                  // we replace the "+" to space and then encode space to "%20" otherwise after creating URLComponents object
                  // it's not possible to distinguish the real percent from the space in the original URL
                  let plusEncodedString = self.absoluteString.replacingOccurrences(of: "+", with: "%20")
      
                  if let queryItems = URLComponents(string: plusEncodedString)?.queryItems {
                      queryItems.forEach { queryItemsDictionary[$0.name] = $0.value }
                  }
                  return queryItemsDictionary
              }
          }
      

      该扩展将允许您解析同时编码 + 符号和带有加号的空格的 URL,例如:

      https://stackoverflow.com/?q=First+question&email=mail%2B10@mail.com
      

      该扩展程序会将“q”解析为“第一个问题”,将“email”解析为“mail+10@mail.com”

      【讨论】:

        【解决方案9】:
        protocol ParametersConvertible {
            func asParameters() -> [String:Any] 
        }
        
        protocol QueryStringConvertible {
            func asQuery() -> String
        }
        
        extension QueryStringConvertible where Self: ParametersConvertible {
            func asQuery() -> String {
                var queries: [URLQueryItem] = []
                for (key, value) in self.asParameters() {
                    queries.append(.init(name: key, value: "\(value)"))
                }
        
                guard var components = URLComponents(string: "") else {
                    return ""
                }
        
                components.queryItems = queries
                return components.percentEncodedQuery ?? ""
            }
        }
        

        【讨论】:

          【解决方案10】:

          将此功能添加到您的控制器

          func getQueryString(params : [String : Any])-> String{
          
                  let urlParams = params.compactMap({ (key, value) -> String in
                      return "\(key)=\(value)"
                  }).joined(separator: "&")
                  var urlString = "?" + urlParams
                  if let url = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed){
                      urlString = url
                  }
                    return urlString
              }
          

          示例

          self.getQueryString(params: ["name" : "deep ios developer" , "age" :22])

          【讨论】:

            【解决方案11】:

            适合任何想要“短、短”版本的人。

            使用 map 进行压缩,您不需要 forEach 或 for 循环。对字典的类型强制也有协议约束。

            extension Dictionary where Key : StringProtocol, Value : StringProtocol {
                var queryString: String {
                    self.map { "\($0)=\($1)" }.joined(separator: "&")
                }
            }
            

            【讨论】:

              【解决方案12】:

              我写了这个helper fn,我认为它很干净:

              private static func queryStringParamsToString(_ dictionary: [String: Any]) -> String {
                  return dictionary
                      .map({(key, value) in "\(key)=\(value)"})
                      .joined(separator: "&")
                      .addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)!
              
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2023-01-04
                • 2015-04-09
                • 1970-01-01
                • 1970-01-01
                • 2015-06-19
                • 2016-07-29
                • 2017-03-16
                • 2019-01-15
                相关资源
                最近更新 更多