web-dev-qa-db-ja.com

SwiftでJSON文字列をオブジェクトに変換するシンプルでクリーンな方法

私はかなり簡単な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
  }
  ...
]

誰かがこれを案内してくれたら嬉しいです。

ありがとう。

71
Hasan Nizamani

簡単な例から始める方法のヒントを次に示します。

次のような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 (別名??

それがあなたが物事を整理するのに役立つことを願っています、

50
Maxim Shoustin

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";
}
*/
25
PassKit

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バージョンに更新されました

8
swiftBoy

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リポジトリにあります。楽しむ!

7
isair

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)

詳細な背景については、 この優れたガイド をご覧ください。

7
Noyer282

iOS 10Swift 3の場合、 AlamofireGloss を使用:

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、これは断然最もエレガントなソリューションです。

4
Timeless

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)
3
Danny Narváez

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
        }
    }
2
MR_22
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)")
2
Munish Kapoor

JSONstructまたは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
    }
}
1
Rugmangathan

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 {}
1
Vitya Shurapov

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)
        }
    }
} 
1
Mohamed Saleh

以下は、物事をより簡単で簡単にするためのサンプルです。データベース内の文字列データは、次のような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()
}
0
hardiBSalih