Swift에서 JSON 문자열을 Object로 변환하는 간단하고 깨끗한 방법
상당히 간단한 JSON 문자열을 Swift에서 객체 유형으로 변환 할 수있는 날을 찾고 있었지만 아무 소용이 없습니다.
다음은 웹 서비스 호출을위한 코드입니다.
func GetAllBusiness() {
Alamofire.request(.GET, "http://MyWebService/").responseString { (request, response, string, error) in
println(string)
}
}
빠른 구조체 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(일명 ??)
문제를 해결하는 데 도움이되기를 바랍니다.
신속한 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
간단한 문자열 확장으로 충분합니다.
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";
}
*/
대한 스위프트 4
@ Passkit 논리를 사용했지만 Swift 4에 따라 업데이트해야했습니다.
Step.1 String Class 확장 생성
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 이것은 내 뷰 컨트롤러에서 사용한 방법입니다.
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 & 글로스 :
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")
}
}
여기에 카테고리 클래스가 있습니다.
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 , 내가 사용이 확장 쓴 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)
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)")
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
}
}
swift.quicktype.io 를 사용 JSON하여 struct또는 class. 코드를 생성하기 위해 신속한 버전을 언급 할 수도 있습니다.
예제 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
}
}
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)
}
}
}
SWIFT4 -JSON 문자열을 Struct로 디코딩하는 쉽고 우아한 방법.
첫 번째 단계 -.utf8 인코딩을 사용하여 문자열을 데이터로 인코딩합니다.
데이터를 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 {}
다음은 작업을 더 간단하고 쉽게 만들 수있는 샘플입니다. 내 데이터베이스의 내 문자열 데이터는 다음과 같은 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)
}}
Third, create My Srevices Class to handle my String Data like this:
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
}}
Finally, call this Function from the View Controller to load data in the table view like this:
func handlingJsonStringData(){
moreData.removeAll(keepingCapacity: false)
moreData = Services.instance.loadMoreDataByString(byString: jsonString)
print(self.moreData.count)
tableView.reloadData()
}
'IT TIP' 카테고리의 다른 글
| 분기 예측 자에게 분기를 따를 가능성이 얼마나됩니까? (0) | 2020.10.23 |
|---|---|
| JSON에 대한 JavaScript 연관 배열 (0) | 2020.10.23 |
| C #에서 여러 문자열 요소 바꾸기 (0) | 2020.10.23 |
| __eq__는 파이썬에서 어떻게 그리고 어떤 순서로 처리됩니까? (0) | 2020.10.23 |
| jQuery를 사용할 때 변수 앞에 "$"를 붙여야하는시기와 이유는 무엇입니까? (0) | 2020.10.23 |