gpt4 book ai didi

json - 在 Swift 中将 JSON 或其他非类型化数据转换为类型化类的最佳方法?

转载 作者:搜寻专家 更新时间:2023-11-01 05:43:22 25 4
gpt4 key购买 nike

为了安全/方便,我正在尝试将 JSON 解析为类型化类,但事实证明它非常笨拙。我找不到图书馆,甚至找不到 Swift 的帖子(Jastor 是我得到的最接近的)。这是一个捏造的小片段来说明:

// From NSJSONSerialization or similar and casted to an appropriate toplevel type (e.g. Dictionary). 
var parsedJson: Dictionary<String, AnyObject> = [ "int" : 1, "nested" : [ "bool" : true ] ]

class TypedObject {
let stringValueWithDefault: String = ""
let intValueRequired: Int
let nestedBoolBroughtToTopLevel: Bool = false
let combinedIntRequired: Int

init(fromParsedJson json: NSDictionary) {
if let parsedStringValue = json["string"] as? String {
self.stringValueWithDefault = parsedStringValue
}

if let parsedIntValue = json["int"] as? Int {
self.intValueRequired = parsedIntValue
} else {
// Raise an exception...?
}

// Optional-chaining is actually pretty nice for this; it keeps the blocks from nesting absurdly.
if let parsedBool = json["nested"]?["bool"] as? Bool {
self.nestedBoolBroughtToTopLevel = parsedBool
}

if let parsedFirstInt = json["firstInt"] as? Int {
if let parsedSecondInt = json["secondInt"] as? Int {
self.combinedIntRequired = parsedFirstInt * parsedSecondInt
}
}
// Most succinct way to error if we weren't able to construct self.combinedIntRequired?
}
}

TypedObject(fromParsedJson: parsedJson)

这里有一些我希望解决的问题:

  1. 它非常冗长,因为为了安全起见,我需要将每个属性包装在复制粘贴的 if-let 中。
  2. 我不确定在缺少所需属性时如何传达错误(如上所述)。 Swift 似乎更喜欢(?)使用异常来解决停止问题(而不是像这里的行人畸形数据)。
  3. 我不知道处理存在但类型错误的属性的好方法(假设 as? 转换将失败并简单地跳过该 block ,这对用户)。
  4. 如果我想将几个属性转换为一个属性,我需要嵌套 let block ,与我要组合的属性数量成比例。 (这可能更普遍地是将多个可选值安全地组合成一个值的问题)。

一般来说,当我觉得我应该能够做一些更具声明性的事情时,我会编写命令式解析逻辑(使用某些规定的 JSON 模式或至少从类定义中推断模式)。

最佳答案

我使用 Jastor 执行此操作框架:

1) 实现一个具有返回 NSDictionary 响应的单一函数的协议(protocol):

protocol APIProtocol {
func didReceiveResponse(results: NSDictionary)
}

2) 创建一个定义 NSURLConnection 对象的 API 类,该对象可用作 iOS 网络 API 的请求 URL。创建此类只是为了从 itunes.apple.com API 返回有效负载。

class API: NSObject {

var data: NSMutableData = NSMutableData()
var delegate: APIProtocol?

func searchItunesFor(searchTerm: String) {

// Clean up the search terms by replacing spaces with +
var itunesSearchTerm = searchTerm.stringByReplacingOccurrencesOfString(" ", withString: "+",
options: NSStringCompareOptions.CaseInsensitiveSearch, range: nil)

var escapedSearchTerm = itunesSearchTerm.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
var urlPath = "https://itunes.apple.com/search?term=\(escapedSearchTerm)&media=music"
var url: NSURL = NSURL(string: urlPath)
var request: NSURLRequest = NSURLRequest(URL: url)
var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)

println("Search iTunes API at URL \(url)")

connection.start()
}

// NSURLConnection Connection failed.
func connection(connection: NSURLConnection!, didFailWithError error: NSError!) {
println("Failed with error:\(error.localizedDescription)")
}

// New request so we need to clear the data object.
func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
self.data = NSMutableData()
}

// Append incoming data.
func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
self.data.appendData(data)
}

// NSURLConnection delegate function.
func connectionDidFinishLoading(connection: NSURLConnection!) {

// Finished receiving data and convert it to a JSON object.
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data,
options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary

delegate?.didReceiveResponse(jsonResult)
}

}

3) 创建一个具有从 Jastor 继承的关联属性的类

NSDictionary 响应:

{
"resultCount" : 50,
"results" : [
{
"collectionExplicitness" : "notExplicit",
"discCount" : 1,
"artworkUrl60" : "http:\/\/a4.mzstatic.com\/us\/r30\/Features\/2a\/b7\/da\/dj.kkirmfzh.60x60-50.jpg",
"collectionCensoredName" : "Changes in Latitudes, Changes in Attitudes (Ultmate Master Disk Gold CD Reissue)"
}
]
}

Music.swift

class Music : Jastor {

var resultCount: NSNumber = 0

}

4) 然后在您的 ViewController 中确保将委托(delegate)设置为 self,然后调用 API 的 searchITunesFor() 方法。

var api: API = API()

override func viewDidLoad() {

api.delegate = self;
api.searchItunesFor("Led Zeppelin")

}

5) 为didReceiveResponse() 实现Delegate 方法。 Jastor 扩展您的类以设置从 iTunes API 返回的结果的 NSDictionary

// #pragma - API Delegates

func didReceiveResponse(results: NSDictionary) {
let music = Music(dictionary: results)
println(music)
}

关于json - 在 Swift 中将 JSON 或其他非类型化数据转换为类型化类的最佳方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24235673/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com