ios 如何快速解析 JSON 文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24013410/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to parse a JSON file in swift?
提问by kmithi
I have a JSON file, want to parse and use list of objects in table view. Can any one share the code to parse JSON file in swift.
我有一个 JSON 文件,想在表视图中解析和使用对象列表。任何人都可以分享快速解析JSON文件的代码吗?
回答by akashivskyy
Couldn't be more simple:
再简单不过了:
import Foundation
let jsonData: Data = /* get your json data */
let jsonDict = try JSONSerialization.jsonObject(with: jsonData) as? NSDictionary
That being said, I strongly recommend using Codable APIsintroduced in Swift 4.
话虽如此,我强烈建议使用Swift 4 中引入的Codable API。
回答by Kirit Modi
Making the API Request
发出 API 请求
var request: NSURLRequest = NSURLRequest(URL: url)
var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)
Preparing for the response
准备响应
Declare an array as below
声明一个数组如下
var data: NSMutableData = NSMutableData()
Receiving the response
接收响应
1.
1.
func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
// Received a new request, clear out the data object
self.data = NSMutableData()
}
2.
2.
func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
// Append the received chunk of data to our data object
self.data.appendData(data)
}
3.
3.
func connectionDidFinishLoading(connection: NSURLConnection!) {
// Request complete, self.data should now hold the resulting info
// Convert the retrieved data in to an object through JSON deserialization
var err: NSError
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
if jsonResult.count>0 && jsonResult["results"].count>0 {
var results: NSArray = jsonResult["results"] as NSArray
self.tableData = results
self.appsTableView.reloadData()
}
}
When NSURLConnection
receives a response, we can expect the didReceiveResponse
method to be called on our behalf. At this point we simply reset our data by saying self.data = NSMutableData()
, creating a new empty data object.
当NSURLConnection
收到响应时,我们可以期望didReceiveResponse
代表我们调用该方法。在这一点上,我们只需说 重置我们的数据self.data = NSMutableData()
,创建一个新的空数据对象。
After a connection is made, we will start receiving data in the method didReceiveData
. The data argument being passed in here is where all our juicy information comes from. We need to hold on to each chunk that comes in, so we append it to the self.data object we cleared out earlier.
建立连接后,我们将开始在方法中接收数据didReceiveData
。这里传入的数据参数是我们所有多汁信息的来源。我们需要保留进入的每个块,因此我们将其附加到我们之前清除的 self.data 对象中。
Finally, when the connection is done and all data has been received, connectionDidFinishLoading
is called and we're ready to use the data in our app. Hooray!
最后,当连接完成并接收到所有数据时,connectionDidFinishLoading
调用 ,我们准备在我们的应用程序中使用数据。万岁!
The connectionDidFinishLoading
method here uses the NSJSONSerialization
class to convert our raw data in to useful Dictionary
objects by deserializing the results from your Url.
connectionDidFinishLoading
这里的方法使用NSJSONSerialization
类Dictionary
通过反序列化来自 Url 的结果将我们的原始数据转换为有用的对象。
回答by dankogai
I just wrote a class called JSON, which makes JSON handling in Swift as easy as JSON object in ES5.
我刚刚写了一个名为 JSON 的类,它使 Swift 中的 JSON 处理就像 ES5 中的 JSON 对象一样简单。
Turn your swift object to JSON like so:
像这样将您的 swift 对象转换为 JSON:
let obj:[String:AnyObject] = [
"array": [JSON.null, false, 0, "",[],[:]],
"object":[
"null": JSON.null,
"bool": true,
"int": 42,
"double": 3.141592653589793,
"string": "a α\t弾\n",
"array": [],
"object": [:]
],
"url":"http://blog.livedoor.com/dankogai/"
]
let json = JSON(obj)
json.toString()
...or string...
...或字符串...
let json = JSON.parse("{\"array\":[...}")
...or URL.
...或网址。
let json = JSON.fromURL("http://api.dan.co.jp/jsonenv")
Tree Traversal
Just traverse elements via subscript:
只需通过下标遍历元素:
json["object"]["null"].asNull // NSNull()
// ...
json["object"]["string"].asString // "a α\t弾\n"
json["array"][0].asNull // NSNull()
json["array"][1].asBool // false
// ...
Just like SwiftyJSONyou don't worry if the subscripted entry does not exist.
就像SwiftyJSON一样,如果下标条目不存在,您也不必担心。
if let b = json["noexistent"][1234567890]["entry"].asBool {
// ....
} else {
let e = json["noexistent"][1234567890]["entry"].asError
println(e)
}
If you are tired of subscripts, add your scheme like so:
如果您厌倦了下标,请像这样添加您的方案:
//// schema by subclassing
class MyJSON : JSON {
init(_ obj:AnyObject){ super.init(obj) }
init(_ json:JSON) { super.init(json) }
var null :NSNull? { return self["null"].asNull }
var bool :Bool? { return self["bool"].asBool }
var int :Int? { return self["int"].asInt }
var double:Double? { return self["double"].asDouble }
var string:String? { return self["string"].asString }
}
And you go:
然后你去:
let myjson = MyJSON(obj)
myjson.object.null
myjson.object.bool
myjson.object.int
myjson.object.double
myjson.object.string
// ...
Hope you like it.
希望你喜欢。
With the new xCode 7.3+ its important to add your domain to the exception list (How can I add NSAppTransportSecurity to my info.plist file?), refer to this posting for instructions, otherwise you will get a transport authority error.
使用新的 xCode 7.3+,将您的域添加到例外列表很重要(如何将 NSAppTransportSecurity 添加到我的 info.plist 文件?),请参阅此帖子以获取说明,否则您将收到传输权限错误。
回答by Ciprian Rarau
Here is a code to make the conversions between JSON and NSData in Swift 2.0
这是在 Swift 2.0 中进行 JSON 和 NSData 之间转换的代码
// Convert from NSData to json object
func nsdataToJSON(data: NSData) -> AnyObject? {
do {
return try NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers)
} catch let myJSONError {
print(myJSONError)
}
return nil
}
// Convert from JSON to nsdata
func jsonToNSData(json: AnyObject) -> NSData?{
do {
return try NSJSONSerialization.dataWithJSONObject(json, options: NSJSONWritingOptions.PrettyPrinted)
} catch let myJSONError {
print(myJSONError)
}
return nil;
}
回答by Robert Dresler
Codable
可编码
In Swift 4+ is strongly recommended to use Codable
instead of JSONSerialization
.
在斯威夫特4+强烈建议使用Codable
代替JSONSerialization
。
This Codable
includes two protocols: Decodable
and Encodable
. This Decodable
protocol allows you to decode Data
in JSON format to custom struct/class conforming to this protocol.
这Codable
包括两个协议:Decodable
和Encodable
. 此Decodable
协议允许您以Data
JSON 格式解码为符合此协议的自定义结构/类。
For example imagine situation that we have this simple Data
(array of two objects)
例如,想象一下我们有这个简单的情况Data
(两个对象的数组)
let data = Data("""
[
{"name":"Steve","age":56},
{"name":"iPhone","age":11}
]
""".utf8)
then have following struct
and implement protocol Decodable
然后遵循struct
并实施协议Decodable
struct Person: Decodable {
let name: String
let age: Int
}
now you can decode your Data
to your array of Person
using JSONDecoder
where first parameter is type conforming to Decodable
and to this type should Data
be decoded
现在你可以解码你Data
的Person
使用数组,JSONDecoder
其中第一个参数的类型符合Decodable
并且应该Data
解码这个类型
do {
let people = try JSONDecoder().decode([Person].self, from: data)
} catch { print(error) }
... note that decoding has to be marked with try
keyword since you could for example make some mistake with naming and then your model can't be decoded correctly ... so you should put it inside do-try-catch block
...请注意,解码必须用try
关键字标记,因为例如您可能会在命名时犯一些错误,然后您的模型无法正确解码...所以您应该将它放在 do-try-catch 块中
Cases that key in json is different from name of property:
json中key与属性名不同的情况:
If key is in named using snake_case, you can set decoder's
keyDecodingStrategy
toconvertFromSnakeCase
which changes key fromproperty_name
to camelCasepropertyName
let decoder = JSONDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase let people = try decoder.decode([Person].self, from: data)
If you need unique name you can use coding keysinside struct/class where you declare name of key
let data = Data(""" { "userName":"Codable", "age": 1 } """.utf8) struct Person: Decodable { let name: String let age: Int enum CodingKeys: String, CodingKey { case name = "userName" case age } }
如果密钥在使用snake_case命名,你可以设置解码器的
keyDecodingStrategy
以convertFromSnakeCase
从变化的关键property_name
,以驼峰propertyName
let decoder = JSONDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase let people = try decoder.decode([Person].self, from: data)
如果您需要唯一的名称,您可以在声明键名称的结构/类中使用编码键
let data = Data(""" { "userName":"Codable", "age": 1 } """.utf8) struct Person: Decodable { let name: String let age: Int enum CodingKeys: String, CodingKey { case name = "userName" case age } }
回答by Prine
I also wrote a small library which is specialized for the mapping of the json response into an object structure. I am internally using the library json-swift from David Owens. Maybe it is useful for someone else.
我还编写了一个小型库,专门用于将 json 响应映射到对象结构。我在内部使用 David Owens 的库 json-swift。也许它对其他人有用。
https://github.com/prine/ROJSONParser
https://github.com/prine/ROJSONParser
Example Employees.json
示例员工.json
{
"employees": [
{
"firstName": "John",
"lastName": "Doe",
"age": 26
},
{
"firstName": "Anna",
"lastName": "Smith",
"age": 30
},
{
"firstName": "Peter",
"lastName": "Jones",
"age": 45
}]
}
As next step you have to create your data model (EmplyoeeContainer and Employee).
下一步,您必须创建数据模型(EmplyoeeContainer 和 Employee)。
Employee.swift
员工.swift
class Employee : ROJSONObject {
required init() {
super.init();
}
required init(jsonData:AnyObject) {
super.init(jsonData: jsonData)
}
var firstname:String {
return Value<String>.get(self, key: "firstName")
}
var lastname:String {
return Value<String>.get(self, key: "lastName")
}
var age:Int {
return Value<Int>.get(self, key: "age")
}
}
EmployeeContainer.swift
EmployeeContainer.swift
class EmployeeContainer : ROJSONObject {
required init() {
super.init();
}
required init(jsonData:AnyObject) {
super.init(jsonData: jsonData)
}
lazy var employees:[Employee] = {
return Value<[Employee]>.getArray(self, key: "employees") as [Employee]
}()
}
Then to actually map the objects from the JSON response you only have to pass the data into the EmployeeContainer class as param in the constructor. It does automatically create your data model.
然后要从 JSON 响应中实际映射对象,您只需将数据作为构造函数中的参数传递到 EmployeeContainer 类中。它会自动创建您的数据模型。
var baseWebservice:BaseWebservice = BaseWebservice();
var urlToJSON = "http://prine.ch/employees.json"
var callbackJSON = {(status:Int, employeeContainer:EmployeeContainer) -> () in
for employee in employeeContainer.employees {
println("Firstname: \(employee.firstname) Lastname: \(employee.lastname) age: \(employee.age)")
}
}
baseWebservice.get(urlToJSON, callback:callbackJSON)
The console output looks then like the following:
控制台输出如下所示:
Firstname: John Lastname: Doe age: 26
Firstname: Anna Lastname: Smith age: 30
Firstname: Peter Lastname: Jones age: 45
回答by Mike Rapadas
SwiftJSONParse: Parse JSON like a badass
SwiftJSONParse:像坏蛋一样解析 JSON
Dead-simple and easy to read!
简单易读!
Example: get the value "mrap"
from nicknames
as a String from this JSON response
例如:获取值"mrap"
从nicknames
作为从该JSON响应字符串
{
"other": {
"nicknames": ["mrap", "Mikee"]
}
It takes your json data NSData
as it is, no need to preprocess.
它NSData
按原样使用您的 json 数据,无需预处理。
let parser = JSONParser(jsonData)
if let handle = parser.getString("other.nicknames[0]") {
// that's it!
}
Disclaimer: I made this and I hope it helps everyone. Feel free to improve on it!
免责声明:我做了这个,我希望它可以帮助大家。随意改进它!
回答by Perry Tribolet
Parsing JSON in Swift is an excellent job for code generation. I've created a tool at http://www.guideluxe.com/JsonToSwiftto do just that.
在 Swift 中解析 JSON 是代码生成的出色工作。我在http://www.guideluxe.com/JsonToSwift上创建了一个工具来做到这一点。
You supply a sample JSON object with a class name and the tool will generate a corresponding Swift class, as well as any needed subsidiary Swift classes, to represent the structure implied by the sample JSON. Also included are class methods used to populate Swift objects, including one that utilizes the NSJSONSerialization.JSONObjectWithData method. The necessary mappings from the NSArray and NSDictionary objects are provided.
您提供一个带有类名的示例 JSON 对象,该工具将生成一个相应的 Swift 类,以及任何需要的附属 Swift 类,以表示示例 JSON 所隐含的结构。还包括用于填充 Swift 对象的类方法,包括使用 NSJSONSerialization.JSONObjectWithData 方法的类方法。提供了来自 NSArray 和 NSDictionary 对象的必要映射。
From the generated code, you only need to supply an NSData object containing JSON that matches the sample provided to the tool.
从生成的代码中,您只需要提供一个包含与提供给工具的示例相匹配的 JSON 的 NSData 对象。
Other than Foundation, there are no dependencies.
除了 Foundation 之外,没有任何依赖项。
My work was inspired by http://json2csharp.com/, which is very handy for .NET projects.
我的工作受到http://json2csharp.com/ 的启发,这对于 .NET 项目非常方便。
Here's how to create an NSData object from a JSON file.
以下是如何从 JSON 文件创建 NSData 对象。
let fileUrl: NSURL = NSBundle.mainBundle().URLForResource("JsonFile", withExtension: "json")!
let jsonData: NSData = NSData(contentsOfURL: fileUrl)!
回答by OWADVL
- Install Swifty Json
Note:if you are looking for this, there's also a high chance you don't know how to install swifty
. Follow the instructions here.
注意:如果您正在寻找这个,您也很可能不知道如何安装swifty
. 按照此处的说明操作。
sudo gem install cocoapods
cd ~/Path/To/Folder/Containing/ShowTracker
Next enter this command:
接下来输入这个命令:
pod init
This will create a default Podfile
for your project. The Podfile
is where you define the dependencies your project relies on.
这将为Podfile
您的项目创建一个默认值。这Podfile
是您定义项目所依赖的依赖项的地方。
Type this command to open Podfile
using Xcode
for editing:
键入此命令可以打开Podfile
使用Xcode
编辑:
open -a Xcode Podfile
Add the Swifty
into the podfile
添加Swifty
到 podfile
platform :ios, '8.0'
use_frameworks!
target 'MyApp' do
pod 'SwiftyJSON', '~> X.X.X'
end
- Check this example
- 检查这个例子
var mURL = NSURL(string: "http://api.openweathermap.org/data/2.5/weather?q=London,uk&units=metric")
if mURL == nil{
println("You are stupid")
return
}
var request = NSURLRequest(URL: mURL!)
NSURLConnection.sendAsynchronousRequest(
request,
queue: NSOperationQueue.mainQueue(),
completionHandler:{ (
response: NSURLResponse!,
data: NSData!,
error: NSError!) -> Void in
if data != nil {
var mJSON = JSON(data: data!)
if let current_conditions = mJSON["weather"][0]["description"].string {
println("Current conditions: " + current_conditions)
} else {
println("MORON!")
}
if let current_temperature = mJSON["main"]["temp"].double {
println("Temperature: "+ String(format:"%.f", current_temperature) + "°C"
} else {
println("MORON!")
}
}
})
回答by Amol Pokale
The entire viewcontroller which show data in collecction view using two methods of json parsig
使用json parsig的两种方法在collection view中显示数据的整个viewcontroller
@IBOutlet weak var imagecollectionview: UICollectionView!
lazy var data = NSMutableData()
var dictdata : NSMutableDictionary = NSMutableDictionary()
override func viewDidLoad() {
super.viewDidLoad()
startConnection()
startNewConnection()
// Do any additional setup after loading the view, typically from a nib.
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return dictdata.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CustomcellCollectionViewCell", forIndexPath: indexPath) as! CustomcellCollectionViewCell
cell.name.text = dictdata.valueForKey("Data")?.valueForKey("location") as? String
let url = NSURL(string: (dictdata.valueForKey("Data")?.valueForKey("avatar_url") as? String)! )
LazyImage.showForImageView(cell.image, url:"URL
return cell
}
func collectionView(collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let kWhateverHeightYouWant = 100
return CGSizeMake(self.view.bounds.size.width/2, CGFloat(kWhateverHeightYouWant))
}
func startNewConnection()
{
let url: URL = URL(string: "YOUR URL" as String)!
let session = URLSession.shared
let request = NSMutableURLRequest(url: url as URL)
request.httpMethod = "GET" //set the get or post according to your request
// request.cachePolicy = NSURLRequest.CachePolicy.ReloadIgnoringCacheData
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let task = session.dataTask(with: request as URLRequest) {
( data, response, error) in
guard let _:NSData = data as NSData?, let _:URLResponse = response, error == nil else {
print("error")
return
}
let jsonString = NSString(data: data!, encoding:String.Encoding.utf8.rawValue) as! String
}
task.resume()
}
func startConnection(){
let urlPath: String = "your URL"
let url: NSURL = NSURL(string: urlPath)!
var request: NSURLRequest = NSURLRequest(URL: url)
var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)!
connection.start()
}
func connection(connection: NSURLConnection!, didReceiveData data: NSData!){
self.data.appendData(data)
}
func buttonAction(sender: UIButton!){
startConnection()
}
func connectionDidFinishLoading(connection: NSURLConnection!) {
do {
let JSON = try NSJSONSerialization.JSONObjectWithData(self.data, options:NSJSONReadingOptions(rawValue: 0))
guard let JSONDictionary :NSDictionary = JSON as? NSDictionary else {
print("Not a Dictionary")
// put in function
return
}
print("JSONDictionary! \(JSONDictionary)")
dictdata.setObject(JSONDictionary, forKey: "Data")
imagecollectionview.reloadData()
}
catch let JSONError as NSError {
print("\(JSONError)")
} }