Swift 3 中的 JSON 解析

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38155436/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 18:29:42  来源:igfitidea点击:

JSON Parsing in Swift 3

jsonxcodeswiftparsing

提问by Nas5296

Has anyone been able to find a way to parse through JSON files in Swift 3? I have been able to get the data to return but I am unsuccessful when it comes to breaking the data down into specific fields. I would post sample code but I've gone through so many different methods unsuccessfully and haven't saved any. The basic format I want to parse through is something like this. Thanks in advance.

有没有人能够找到一种方法来解析 Swift 3 中的 JSON 文件?我已经能够让数据返回,但是在将数据分解为特定字段时我没有成功。我会发布示例代码,但我已经尝试了很多不同的方法但没有成功并且没有保存任何方法。我想解析的基本格式是这样的。提前致谢。

{
  "Language": {

    "Field":[
          {
          "Number":"976",
          "Name":"Test"
          },
          {
          "Number":"977",
          "Name":"Test"
          }
       ]
   }
}

回答by Jeffery Thomas

Have you tried JSONSerialization.jsonObject(with:options:)?

你试过JSONSerialization.jsonObject(with:options:)吗?

var jsonString = "{" +
    "\"Language\": {" +
    "\"Field\":[" +
    "{" +
    "\"Number\":\"976\"," +
    "\"Name\":\"Test\"" +
    "}," +
    "{" +
    "\"Number\":\"977\"," +
    "\"Name\":\"Test\"" +
    "}" +
    "]" +
    "}" +
    "}"

var data = jsonString.data(using: .utf8)!

let json = try? JSONSerialization.jsonObject(with: data)


Swift sometimes produces some very odd syntax.

Swift 有时会产生一些非常奇怪的语法。

if let number = json?["Language"]??["Field"]??[0]?["Number"] as? String {
    print(number)
}

Everything in the JSON object hierarchy ends up getting wrapped as an optional (ie. AnyObject?). Array<T>subscript returns a non-optional T. For this JSON, which is wrapped in an optional, array subscript returns Optional<AnyObject>. However, Dictionary<K, V>subscript returns an Optional<V>. For this JSON, subscript returns the very odd looking Optional<Optional<AnyObject>>(ie. AnyObject??).

JSON 对象层次结构中的所有内容最终都被包装为可选(即AnyObject?)。Array<T>下标返回一个非可选的T. 对于这个包裹在可选数组下标中的 JSON,返回Optional<AnyObject>. 但是,Dictionary<K, V>下标返回一个Optional<V>. 对于这个 JSON,下标返回非常奇怪的外观 Optional<Optional<AnyObject>>(即。AnyObject??)。

  • jsonis an Optional<AnyObject>.
  • json?["Language"]returns an Optional<Optional<AnyObject>>.
  • json?["Language"]??["Field"]returns an Optional<Optional<AnyObject>>.
  • json?["Language"]??["Field"]??[0]returns an Optional<AnyObject>.
  • json?["Language"]??["Field"]??[0]?["Number"]returns an Optional<Optional<AnyObject>>.
  • json?["Language"]??["Field"]??[0]?["Number"] as? Stringreturns an Optional<String>.
  • json是一个Optional<AnyObject>
  • json?["Language"]返回一个Optional<Optional<AnyObject>>.
  • json?["Language"]??["Field"]返回一个Optional<Optional<AnyObject>>.
  • json?["Language"]??["Field"]??[0]返回一个Optional<AnyObject>.
  • json?["Language"]??["Field"]??[0]?["Number"]返回一个Optional<Optional<AnyObject>>.
  • json?["Language"]??["Field"]??[0]?["Number"] as? String返回一个Optional<String>.

The Optional<String>is then used by the if letsyntax to product a String.

Optional<String>,然后由使用if let语法产物String



Final note: iterating the field array looks like this.

最后一点:迭代字段数组看起来像这样。

for field in json?["Language"]??["Field"] as? [AnyObject] ?? [] {
    if let number = field["Number"] as? String {
        print(number)
    }
}


Swift 4 Update

斯威夫特 4 更新

Swift 4 makes this all much easier to deal with. Again we will start with your test data ("""makes this so much nicer).

Swift 4 使这一切变得更容易处理。我们将再次从您的测试数据开始("""使这更好)。

let data = """
{
  "Language": {

    "Field":[
          {
          "Number":"976",
          "Name":"Test"
          },
          {
          "Number":"977",
          "Name":"Test"
          }
       ]
   }
}
""".data(using: .utf8)!


Next we can define classes around the objects used in your JSON.

接下来,我们可以围绕 JSON 中使用的对象定义类。

struct Object: Decodable {
    let language: Language
    enum CodingKeys: String, CodingKey { case language="Language" }
}

struct Language: Decodable {
    let fields: [Field]
    enum CodingKeys: String, CodingKey { case fields="Field" }
}

struct Field: Decodable {
    let number: String
    let name: String
    enum CodingKeys: String, CodingKey { case number="Number"; case name="Name" }
}

The CodingKeysenum is how struct properties are mapped to JSON object member strings. This mapping is done automagically by Decodable.

CodingKeys枚举是结构特性如何映射到JSON对象构件字符串。此映射由 自动完成Decodable



Parsing the JSON now is simple.

现在解析 JSON 很简单。

let object = try! JSONDecoder().decode(Object.self, from: data)

print(object.language.fields[0].name)

for field in object.language.fields {
    print(field.number)
}

回答by serg_zhd

In Xcode 8 and Swift 3idnow imports as Anyrather than AnyObject

Xcode 8 和 Swift 3id现在导入为Any而不是AnyObject

This means that JSONSerialization.jsonObject(with: data)returns Any. So you have to cast the json datato a specific type like [String:Any]. Same applies to the next fields down the json.

这意味着JSONSerialization.jsonObject(with: data)返回Any. 因此,您必须将 jsondata转换为特定类型,例如[String:Any]. 同样适用于 json 中的下一个字段。

var jsonString = "{" +
    "\"Language\": {" +
    "\"Field\":[" +
    "{" +
    "\"Number\":\"976\"," +
    "\"Name\":\"Test1\"" +
    "}," +
    "{" +
    "\"Number\":\"977\"," +
    "\"Name\":\"Test2\"" +
    "}" +
    "]" +
    "}" +
"}"

var data = jsonString.data(using: .utf8)!
if let parsedData = try? JSONSerialization.jsonObject(with: data) as! [String:Any] {
    let language = parsedData["Language"] as! [String:Any]
    print(language)
    let field = language["Field"] as! [[String:Any]]
    let name = field[0]["Name"]!
    print(name) // ==> Test1
}

In practice you would probably want some specific field buried in the json. Lets assume it's the Namefield of the first element of Fieldarray. You can use a chain of unwraps like this to safely access the field:

在实践中,您可能希望将某些特定字段埋在 json 中。让我们假设它NameField数组的第一个元素的字段。您可以使用这样的解包链来安全地访问该字段:

var data = jsonString.data(using: .utf8)!
if let json = try? JSONSerialization.jsonObject(with: data) as? [String:Any],
    let language = json?["Language"] as? [String:Any],
    let field = language["Field"] as? [[String:Any]],
    let name = field[0]["Name"] as? String, field.count > 0 {
    print(name) // ==> Test1
} else {
    print("bad json - do some recovery")
}

Also you may want to check Apple's Swift Blog Working with JSON in Swift

您也可能想查看 Apple 的 Swift 博客在 Swift 中使用 JSON

回答by Gene De Lisa

Shoving JSON into a string manually is a pita. Why don't you just put the JSON into a file and read that in?

手动将 JSON 推入字符串是一种皮塔饼。你为什么不把 JSON 放入一个文件并读入呢?

Swift 3:

斯威夫特 3:

let bundle = Bundle(for: type(of: self))
    if let theURL = bundle.url(forResource: "response", withExtension: "json") {
        do {
            let data = try Data(contentsOf: theURL)
            if let parsedData = try? JSONSerialization.jsonObject(with: data) as! [String:Any] {
                grok(parsedData)
            }
        } catch {
            print(error)
        }
    }

回答by BhuShan PaWar

 override func viewDidLoad() {
        super.viewDidLoad()
        let url=URL(string:"http://api.androidhive.info/contacts/")
        do {
            let allContactsData = try Data(contentsOf: url!)
            let allContacts = try JSONSerialization.jsonObject(with: allContactsData, options: JSONSerialization.ReadingOptions.allowFragments) as! [String : AnyObject]
            if let arrJSON = allContacts["contacts"] {
                for index in 0...arrJSON.count-1 {
                    let aObject = arrJSON[index] as! [String : AnyObject]
                    names.append(aObject["name"] as! String)
                    contacts.append(aObject["email"] as! String)
                }
            }
            print(names)
            print(contacts)
            self.tableView.reloadData()
        }
        catch {
        }
    }

回答by ismailtsn92

Use SwiftJson library. I think its very easy way to parse.

使用 SwiftJson 库。我认为它的解析方法非常简单。

let count: Int? = json["Field"].array?.count
if let ct = count {            
    for index in 0...ct-1{
        let number = json ["Field"][index]["number"].string
        let name = json ["Field"][index]["name"].string 

....

....

like this .

像这样 。

回答by Ashis Laha

JSON Parsing in swift 4 using Decodable Protocol :

使用可解码协议在 swift 4 中进行 JSON 解析:

I create a mocky file using your json object :

我使用您的 json 对象创建了一个模拟文件:

http://www.mocky.io/v2/5a280c282f0000f92c0635e6

http://www.mocky.io/v2/5a280c282f0000f92c0635e6

Here is the code to parse the JSON :

这是解析 JSON 的代码:

Model Creation :

模型创建:

import UIKit

struct Item : Decodable { 
// Properties must be the same name as specified in JSON , else it will return nil
var Number : String
var Name : String
}

struct Language : Decodable {
 var Field : [Item]
}

struct Result : Decodable {
 var Language : Language
}

You can use optional in the model if you are uncertain that something might be missing in JSON file.

如果您不确定 JSON 文件中可能缺少某些内容,则可以在模型中使用 optional 。

This is the parsing Logic :

这是解析逻辑:

class ViewController: UIViewController {

let url = "http://www.mocky.io/v2/5a280c282f0000f92c0635e6"

private func parseJSON() {

    guard let url = URL(string: url) else { return }

    let session = URLSession.shared.dataTask(with: url) { (data, response, error) in
        guard let data = data else { return }
        guard let result = try? JSONDecoder().decode(Result.self, from: data) else { return }
        print("\n\nResult : \(result)")
    }
    session.resume()
}

override func viewDidLoad() {
    super.viewDidLoad()
    parseJSON()
}
}

The Print Output :

打印输出:

 Result : Result(Language: JSON_Parsing.Language(Field: [JSON_Parsing.Item(Number: "976", Name: "Test"), JSON_Parsing.Item(Number: "977", Name: "Test")]))

This the github Project link. You can check.

这是 github 项目链接。你可以检查。

回答by Ashis Laha

JSON Parsing using Swift 4 in Simple WAY

以简单的方式使用 Swift 4 进行 JSON 解析

   let url = URL(string: "http://mobileappdevelop.co/TIPIT/webservice/get_my_groups?user_id=5")
    URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in
        guard let data = data, error == nil else { return }

        do {
            let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String:Any]

             print(json)

            let posts =  json["Field"] as? [[String: Any]] ?? []
            print(posts)
        } catch let error as NSError {
            print(error)
        }

    }).resume()

}

回答by Rizwan Shaikh

dict = {
    message = "Login successfully.";
    status = 1;
    "user_details" =     (
                {
            dob = "1900-11-18";
            email = "[email protected]";
            gender = male;
            name = Rizwan;
            nickname = Shaikh;
            "profile_pic" = "1483434421.jpeg";
            "social_id" = "<null>";
            "user_id" = 2;
        }
    );
}

We can parse above json in Swift 3 as

我们可以在 Swift 3 中将上面的 json 解析为

var dict2  = dict as! [String : Any]
print(dict);
let demoStr = dict2["message"] as! String
print(demoStr)
let demoArray = dict2["user_details"] as! [Any]
let demoDict = demoArray[0] as! [String:Any]
print(demoDict["dob"]!)