JSON Parsing in Swift 3
Кто-нибудь смог найти способ разобрать файлы JSON в Swift 3? Мне удалось вернуть данные, но я не увенчался успехом, когда дело дошло до разбивки данных на определенные поля. Я бы опубликовал образец кода, но я прошел через множество разных методов безуспешно и не сохранил. Основной формат, который я хочу проанализировать, - это что-то вроде этого. Спасибо заранее.
{
"Language": {
"Field":[
{
"Number":"976",
"Name":"Test"
},
{
"Number":"977",
"Name":"Test"
}
]
}
}
Ответы
Ответ 1
Вы пробовали 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 иногда создает очень нечетный синтаксис.
if let number = json?["Language"]??["Field"]??[0]?["Number"] as? String {
print(number)
}
Все в иерархии объектов JSON заканчивается завершением в качестве необязательного (т.е. AnyObject?
). Array<T>
индекс возвращает необязательный T
. Для этого JSON, который завернут в необязательный, индекс массива возвращает Optional<AnyObject>
. Однако индекс Dictionary<K, V>
возвращает Optional<V>
. Для этого JSON индекс возвращает очень странный вид
Optional<Optional<AnyObject>>
(т.е. AnyObject??
).
-
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>
.
Затем Optional<String>
используется синтаксисом if let
для продукта a String
.
Заключительное примечание: итерация массива полей выглядит следующим образом.
for field in json?["Language"]??["Field"] as? [AnyObject] ?? [] {
if let number = field["Number"] as? String {
print(number)
}
}
Обновление Swift 4
Swift 4 упрощает работу с этим. Снова мы начнем с ваших тестовых данных ("""
делает это намного приятнее).
let data = """
{
"Language": {
"Field":[
{
"Number":"976",
"Name":"Test"
},
{
"Number":"977",
"Name":"Test"
}
]
}
}
""".data(using: .utf8)!
Далее мы можем определить классы вокруг объектов, используемых в вашем 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" }
}
Переменная CodingKeys
перечисляет, как свойства структуры сопоставляются с строками-членами объекта JSON. Это отображение выполняется автоматом Decodable
.
Анализ 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)
}
Ответ 2
В Xcode 8 и Swift 3 id
теперь импортируется как Any
, а не AnyObject
Это означает, что JSONSerialization.jsonObject(with: data)
возвращает Any
. Поэтому вам нужно отбросить json data
до определенного типа, например [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
}
На практике вам, вероятно, понадобится какое-то конкретное поле, захороненное в json. Предположим, что это поле Name
первого элемента массива Field
. Для безопасного доступа к полю вы можете использовать цепочку разверток, например:
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")
}
Также вы можете проверить Apple Swift Blog Работа с JSON в Swift
Ответ 3
Перемещение JSON в строку вручную - это лаваш. Почему бы вам просто не положить JSON в файл и прочитать это?
Swift 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)
}
}
Ответ 4
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 {
}
}
Ответ 5
Использовать библиотеку 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
....
как это.
Ответ 6
JSON Анализ в режиме быстрого 4 с использованием разрешимого протокола:
Я создаю mocky файл, используя ваш json-объект:
http://www.mocky.io/v2/5a280c282f0000f92c0635e6
Вот код для разбора JSON:
Создание модели:
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
}
Вы можете использовать опцию в модели, если не уверены, что что-то может отсутствовать в файле JSON.
Это логическая синтаксическая разборка:
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()
}
}
Выход печати:
Result : Result(Language: JSON_Parsing.Language(Field: [JSON_Parsing.Item(Number: "976", Name: "Test"), JSON_Parsing.Item(Number: "977", Name: "Test")]))
Это ссылка проекта github. Вы можете проверить.
Ответ 7
JSON Parsing с использованием Swift 4 в Simple WAY
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()
}
Ответ 8
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
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"]!)