私はかなり簡単なJSON文字列をSwiftのオブジェクトタイプに変換するために何日も探していましたが、役に立ちませんでした。
Webサービス呼び出しのコードは次のとおりです。
func GetAllBusiness() {
Alamofire.request(.GET, "http://MyWebService/").responseString { (request, response, string, error) in
println(string)
}
}
Swift構造体Business.Swiftがあります。
struct Business {
var Id : Int = 0
var Name = ""
var Latitude = ""
var Longitude = ""
var Address = ""
}
デプロイされたテストサービスは次のとおりです。
[
{
"Id": 1,
"Name": "A",
"Latitude": "-35.243256",
"Longitude": "149.110701",
"Address": null
},
{
"Id": 2,
"Name": "B",
"Latitude": "-35.240592",
"Longitude": "149.104843",
"Address": null
}
...
]
誰かがこれを案内してくれたら嬉しいです。
ありがとう。
簡単な例から始める方法のヒントを次に示します。
次のようなJSON配列文字列(あなたのものに類似)があると考えてください:
var list:Array<Business> = []
// left only 2 fields for demo
struct Business {
var id : Int = 0
var name = ""
}
var jsonStringAsArray = "[\n" +
"{\n" +
"\"id\":72,\n" +
"\"name\":\"Batata Cremosa\",\n" +
"},\n" +
"{\n" +
"\"id\":183,\n" +
"\"name\":\"Caldeirada de Peixes\",\n" +
"},\n" +
"{\n" +
"\"id\":76,\n" +
"\"name\":\"Batata com Cebola e Ervas\",\n" +
"},\n" +
"{\n" +
"\"id\":56,\n" +
"\"name\":\"Arroz de forma\",\n" +
"}]"
// convert String to NSData
var data: NSData = jsonStringAsArray.dataUsingEncoding(NSUTF8StringEncoding)!
var error: NSError?
// convert NSData to 'AnyObject'
let anyObj: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(0),
error: &error)
println("Error: \(error)")
// convert 'AnyObject' to Array<Business>
list = self.parseJson(anyObj!)
//===============
func parseJson(anyObj:AnyObject) -> Array<Business>{
var list:Array<Business> = []
if anyObj is Array<AnyObject> {
var b:Business = Business()
for json in anyObj as Array<AnyObject>{
b.name = (json["name"] as AnyObject? as? String) ?? "" // to get rid of null
b.id = (json["id"] as AnyObject? as? Int) ?? 0
list.append(b)
}// for
} // if
return list
}//func
[編集]
Nullを削除するには、次のように変更します。
b.name = (json["name"] as AnyObject? as? String) ?? ""
b.id = (json["id"] as AnyObject? as? Int) ?? 0
参照 Coalescing Operator (別名??
)
それがあなたが物事を整理するのに役立つことを願っています、
Swift 3/4
extension String {
func toJSON() -> Any? {
guard let data = self.data(using: .utf8, allowLossyConversion: false) else { return nil }
return try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
}
}
使用例:
let dict = myString.toJSON() as? [String:AnyObject] // can be any type here
単純なString拡張機能で十分なはずです:
extension String {
var parseJSONString: AnyObject? {
let data = self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
if let jsonData = data {
// Will return an object or nil if JSON decoding fails
return NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil)
} else {
// Lossless conversion of the string was not possible
return nil
}
}
}
次に:
var jsonString = "[\n" +
"{\n" +
"\"id\":72,\n" +
"\"name\":\"Batata Cremosa\",\n" +
"},\n" +
"{\n" +
"\"id\":183,\n" +
"\"name\":\"Caldeirada de Peixes\",\n" +
"},\n" +
"{\n" +
"\"id\":76,\n" +
"\"name\":\"Batata com Cebola e Ervas\",\n" +
"},\n" +
"{\n" +
"\"id\":56,\n" +
"\"name\":\"Arroz de forma\",\n" +
"}]"
let json: AnyObject? = jsonString.parseJSONString
println("Parsed JSON: \(json!)")
println("json[3]: \(json![3])")
/* Output:
Parsed JSON: (
{
id = 72;
name = "Batata Cremosa";
},
{
id = 183;
name = "Caldeirada de Peixes";
},
{
id = 76;
name = "Batata com Cebola e Ervas";
},
{
id = 56;
name = "Arroz de forma";
}
)
json[3]: {
id = 56;
name = "Arroz de forma";
}
*/
ForSwift 4
@ Passkit のロジックを使用しましたが、Swift 4に従って更新する必要がありました
Step.1文字列クラス用に作成された拡張機能
import UIKit
extension String
{
var parseJSONString: AnyObject?
{
let data = self.data(using: String.Encoding.utf8, allowLossyConversion: false)
if let jsonData = data
{
// Will return an object or nil if JSON decoding fails
do
{
let message = try JSONSerialization.jsonObject(with: jsonData, options:.mutableContainers)
if let jsonResult = message as? NSMutableArray
{
print(jsonResult)
return jsonResult //Will return the json array output
}
else
{
return nil
}
}
catch let error as NSError
{
print("An error occurred: \(error)")
return nil
}
}
else
{
// Lossless conversion of the string was not possible
return nil
}
}
}
Step.2これがView Controllerで使用した方法です
var jsonString = "[\n" +
"{\n" +
"\"id\":72,\n" +
"\"name\":\"Batata Cremosa\",\n" +
"},\n" +
"{\n" +
"\"id\":183,\n" +
"\"name\":\"Caldeirada de Peixes\",\n" +
"},\n" +
"{\n" +
"\"id\":76,\n" +
"\"name\":\"Batata com Cebola e Ervas\",\n" +
"},\n" +
"{\n" +
"\"id\":56,\n" +
"\"name\":\"Arroz de forma\",\n" +
"}]"
//Convert jsonString to jsonArray
let json: AnyObject? = jsonString.parseJSONString
print("Parsed JSON: \(json!)")
print("json[2]: \(json![2])")
すべてのクレジットは元のユーザーに割り当てられ、最新のSwiftバージョンに更新されました
Swiftでjsonデータとデシリアライゼーションを簡単に処理できるライブラリを作成しました。ここで入手できます: https://github.com/isair/JSONHelper
編集:ライブラリを更新しましたが、これだけで実行できます:
class Business: Deserializable {
var id: Int?
var name = "N/A" // This one has a default value.
required init(data: [String: AnyObject]) {
id <-- data["id"]
name <-- data["name"]
}
}
var businesses: [Business]()
Alamofire.request(.GET, "http://MyWebService/").responseString { (request, response, string, error) in
businesses <-- string
}
古い回答:
まず、.responseStringを使用する代わりに、.responseを使用して応答オブジェクトを取得します。次に、コードを次のように変更します。
func getAllBusinesses() {
Alamofire.request(.GET, "http://MyWebService/").response { (request, response, data, error) in
var businesses: [Business]?
businesses <-- data
if businesses == nil {
// Data was not structured as expected and deserialization failed, do something.
} else {
// Do something with your businesses array.
}
}
}
そして、次のようなビジネスクラスを作成する必要があります。
class Business: Deserializable {
var id: Int?
var name = "N/A" // This one has a default value.
required init(data: [String: AnyObject]) {
id <-- data["id"]
name <-- data["name"]
}
}
完全なドキュメントは、私のGitHubリポジトリにあります。楽しむ!
Swift 4はJSONをよりエレガントに解析します。この単純化された例に従って、構造にコーディング可能なプロトコルを採用するだけです。
struct Business: Codable {
let id: Int
let name: String
}
JSON配列を解析するには、デコーダーにデータ配列のオブジェクトが何であるかを伝えます
let parsedData = decoder.decode([Business].self, from: data)
完全な動作例を次に示します。
import Foundation
struct Business: Codable {
let id: Int
let name: String
}
// Generating the example JSON data:
let originalObjects = [Business(id: 0, name: "A"), Business(id: 1, name: "B")]
let encoder = JSONEncoder()
let data = try! encoder.encode(originalObjects)
// Parsing the data:
let decoder = JSONDecoder()
let parsedData = try! decoder.decode([Business].self, from: data)
詳細な背景については、 この優れたガイド をご覧ください。
iOS 10
&Swift 3
の場合、 Alamofire & Gloss を使用:
Alamofire.request("http://localhost:8080/category/en").responseJSON { response in
if let data = response.data {
if let categories = [Category].from(data: response.data) {
self.categories = categories
self.categoryCollectionView.reloadData()
} else {
print("Casting error")
}
} else {
print("Data is null")
}
}
そして、これがCategoryクラスです
import Gloss
struct Category: Decodable {
let categoryId: Int?
let name: String?
let image: String?
init?(json: JSON) {
self.categoryId = "categoryId" <~~ json
self.name = "name" <~~ json
self.image = "image" <~~ json
}
}
IMO、これは断然最もエレガントなソリューションです。
Swift 4の場合、Codableプロトコルを使用してこの拡張機能を作成しました。
struct Business: Codable {
var id: Int
var name: String
}
extension String {
func parse<D>(to type: D.Type) -> D? where D: Decodable {
let data: Data = self.data(using: .utf8)!
let decoder = JSONDecoder()
do {
let _object = try decoder.decode(type, from: data)
return _object
} catch {
return nil
}
}
}
var jsonString = "[\n" +
"{\n" +
"\"id\":72,\n" +
"\"name\":\"Batata Cremosa\",\n" +
"},\n" +
"{\n" +
"\"id\":183,\n" +
"\"name\":\"Caldeirada de Peixes\",\n" +
"},\n" +
"{\n" +
"\"id\":76,\n" +
"\"name\":\"Batata com Cebola e Ervas\",\n" +
"},\n" +
"{\n" +
"\"id\":56,\n" +
"\"name\":\"Arroz de forma\",\n" +
"}]"
let businesses = jsonString.parse(to: [Business].self)
RDCの応答が好きですが、返されるJSONがトップレベルの配列のみを持つように制限するのはなぜですか?トップレベルで辞書を許可する必要があったので、次のように変更しました。
extension String
{
var parseJSONString: AnyObject?
{
let data = self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
if let jsonData = data
{
// Will return an object or nil if JSON decoding fails
do
{
let message = try NSJSONSerialization.JSONObjectWithData(jsonData, options:.MutableContainers)
if let jsonResult = message as? NSMutableArray {
return jsonResult //Will return the json array output
} else if let jsonResult = message as? NSMutableDictionary {
return jsonResult //Will return the json dictionary output
} else {
return nil
}
}
catch let error as NSError
{
print("An error occurred: \(error)")
return nil
}
}
else
{
// Lossless conversion of the string was not possible
return nil
}
}
let jsonString = "{\"id\":123,\"Name\":\"Munish\"}"
文字列をNSDataに変換
var data: NSData =jsonString.dataUsingEncoding(NSUTF8StringEncoding)!
var error: NSError?
NSDataをAnyObjectに変換
var jsonObject: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: &error)
println("Error: \\(error)")
let id = (jsonObject as! NSDictionary)["id"] as! Int
let name = (jsonObject as! NSDictionary)["name"] as! String
println("Id: \\(id)")
println("Name: \\(name)")
JSON
をstruct
またはclass
に変換するには、 Swift.quicktype.io を使用できます。 Swiftのバージョンに言及してコードを生成することもできます。
JSONの例:
{
"message": "Hello, World!"
}
生成されたコード:
import Foundation
typealias Sample = OtherSample
struct OtherSample: Codable {
let message: String
}
// Serialization extensions
extension OtherSample {
static func from(json: String, using encoding: String.Encoding = .utf8) -> OtherSample? {
guard let data = json.data(using: encoding) else { return nil }
return OtherSample.from(data: data)
}
static func from(data: Data) -> OtherSample? {
let decoder = JSONDecoder()
return try? decoder.decode(OtherSample.self, from: data)
}
var jsonData: Data? {
let encoder = JSONEncoder()
return try? encoder.encode(self)
}
var jsonString: String? {
guard let data = self.jsonData else { return nil }
return String(data: data, encoding: .utf8)
}
}
extension OtherSample {
enum CodingKeys: String, CodingKey {
case message
}
}
Swift4-JSON文字列をStructにデコードする簡単でエレガントな方法。
最初のステップ-.utf8エンコーディングで文字列をデータにエンコードします。
ThanデータをYourDataStructにデコードします。
struct YourDataStruct: Codable {
let type, id: String
init(_ json: String, using encoding: String.Encoding = .utf8) throws {
guard let data = json.data(using: encoding) else {
throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
}
try self.init(data: data)
}
init(data: Data) throws {
self = try JSONDecoder().decode(YourDataStruct.self, from: data)
}
}
do { let successResponse = try WSDeleteDialogsResponse(response) }
} catch {}
SwiftyJSON ライブラリを使用すると、次のようになります。
if let path : String = Bundle.main.path(forResource: "tiles", ofType: "json") {
if let data = NSData(contentsOfFile: path) {
let optData = try? JSON(data: data as Data)
guard let json = optData else {
return
}
for (_, object) in json {
let name = object["name"].stringValue
print(name)
}
}
}
以下は、物事をより簡単で簡単にするためのサンプルです。データベース内の文字列データは、次のようなJSONファイルです。
[{"stype":"noun","sdsc":"careless disregard for consequences","swds":"disregard, freedom, impulse, licentiousness, recklessness, spontaneity, thoughtlessness, uninhibitedness, unrestraint, wantonness, wildness","anwds":"restraint, self-restraint"},{"stype":"verb","sdsc":"leave behind, relinquish","swds":"abdicate, back out, bail out, bow out, chicken out, cop out, cut loose, desert, discard, discontinue, ditch, drop, drop out, duck, dump, dust, flake out, fly the coop, give up the ship, kiss goodbye, leave, leg it, let go, opt out, pull out, quit, run out on, screw, ship out, stop, storm out, surrender, take a powder, take a walk, throw over, vacate, walk out on, wash hands of, withdraw, yield","anwds":"adopt, advance, allow, assert, begin, cherish, come, continue, defend, favor, go, hold, keep, maintain, persevere, pursue, remain, retain, start, stay, support, uphold"},{"stype":"verb","sdsc":"leave in troubled state","swds":"back out, desert, disown, forsake, jilt, leave, leave behind, quit, reject, renounce, throw over, walk out on","anwds":"adopt, allow, approve, assert, cherish, come, continue, defend, favor, keep, pursue, retain, stay, support, uphold"}]
このJSON文字列データを読み込むには、次の簡単な手順に従います。最初に、次のようにMoreDataオブジェクトのクラスを作成します。
class MoreData {
public private(set) var stype : String
public private(set) var sdsc : String
public private(set) var swds : String
public private(set) var anwds : String
init( stype : String, sdsc : String, swds : String, anwds : String) {
self.stype = stype
self.sdsc = sdsc
self.swds = swds
self.anwds = anwds
}}
次に、次のようにJSON文字列の文字列拡張を作成します。
extension String {
func toJSON() -> Any? {
guard let data = self.data(using: .utf8, allowLossyConversion: false) else { return nil }
return try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
}}
3番目に、次のように文字列データを処理するMy Srevicesクラスを作成します。
class Services {
static let instance: Services = Services()
func loadMoreDataByString(byString: String) -> [MoreData]{
var myVariable = [MoreData]()
guard let ListOf = byString.toJSON() as? [[String: AnyObject]] else { return [] }
for object in ListOf {
let stype = object["stype"] as? String ?? ""
let sdsc = object["sdsc"] as? String ?? ""
let swds = object["swds"] as? String ?? ""
let anwds = object["anwds"] as? String ?? ""
let myMoreData = MoreData(stype : stype, sdsc : sdsc, swds : swds, anwds : anwds)
myVariable.append(myMoreData)
}
return myVariable
}}
最後に、View Controllerからこの関数を呼び出して、次のようにテーブルビューにデータをロードします。
func handlingJsonStringData(){
moreData.removeAll(keepingCapacity: false)
moreData = Services.instance.loadMoreDataByString(byString: jsonString)
print(self.moreData.count)
tableView.reloadData()
}