Swift에서 JSON 문자열을 개체로 단순하고 깔끔하게 변환
꽤 간단한 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
}
...
]
누군가 이 일을 안내해주면 기쁠 것 같아요.
감사해요.
신속한 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
여기 간단한 예시로 시작하는 몇 가지 팁이 있습니다.
다음과 같은 JSON Array String(사용하는 것과 유사한)이 있다고 가정합니다.
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
'참조'도 참조해 주세요.??
)
그게 해결하는데 도움이 되길 바라
간단한 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";
}
*/
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)
Swift 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
}
}
}
스텝.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 4의 경우 코드화 프로토콜을 사용하여 다음 확장자를 작성했습니다.
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)
나는 스위프트에서 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 repo에서 확인하실 수 있습니다.재미있게 보내!
★★★의 iOS 10
&Swift 3
Alarmofire & 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, 이것이 단연코 가장 우아한 해결책입니다.
SWIFT4 - JSON 문자열을 Structure로 쉽고 우아하게 디코딩할 수 있습니다.
첫 번째 단계 - .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 {}
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)")
누군가에게 도움이 될 수도 있어요.비슷한 예다.
이것은 우리의Codable
데이터를 바인드하는 클래스입니다.SwiftyJsonAccelerator를 사용하여 이 클래스를 쉽게 만들 수 있습니다.
class ModelPushNotificationFilesFile: Codable {
enum CodingKeys: String, CodingKey {
case url
case id
case fileExtension = "file_extension"
case name
}
var url: String?
var id: Int?
var fileExtension: String?
var name: String?
init (url: String?, id: Int?, fileExtension: String?, name: String?) {
self.url = url
self.id = id
self.fileExtension = fileExtension
self.name = name
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
url = try container.decodeIfPresent(String.self, forKey: .url)
id = try container.decodeIfPresent(Int.self, forKey: .id)
fileExtension = try container.decodeIfPresent(String.self, forKey: .fileExtension)
name = try container.decodeIfPresent(String.self, forKey: .name)
}
}
이것은 Json String입니다.
let jsonString = "[{\"name\":\"\",\"file_extension\":\"\",\"id\":10684,\"url\":\"https:\\/\\/homepages.cae.wisc.edu\\/~ece533\\/images\\/tulips.png\"},
{\"name\":\"\",\"file_extension\":\"\",\"id\":10684,\"url\":\"https:\\/\\/homepages.cae.wisc.edu\\/~ece533\\/images\\/arctichare.png\"},
{\"name\":\"\",\"file_extension\":\"\",\"id\":10684,\"url\":\"https:\\/\\/homepages.cae.wisc.edu\\/~ece533\\/images\\/serrano.png\"},
{\"name\":\"\",\"file_extension\":\"\",\"id\":10684,\"url\":\"https:\\/\\/homepages.cae.wisc.edu\\/~ece533\\/images\\/peppers.png\"},
{\"name\":\"\",\"file_extension\":\"\",\"id\":10684,\"url\":\"https:\\/\\/homepages.cae.wisc.edu\\/~ece533\\/images\\/pool.png\"}]"
여기서는 swift object로 변환합니다.
let jsonData = Data(jsonString.utf8)
let decoder = JSONDecoder()
do {
let fileArray = try decoder.decode([ModelPushNotificationFilesFile].self, from: jsonData)
print(fileArray)
print(fileArray[0].url)
} catch {
print(error.localizedDescription)
}
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
}
}
json을 여러 줄 문자열 리터럴로 랩하여 다음과 같이 해석해 보십시오.
import Foundation
// MARK: - DemoJSON
struct DemoJSON: Codable {
let menu: Menu
}
// MARK: - Menu
struct Menu: Codable {
let id, value: String
let popup: Popup
}
// MARK: - Popup
struct Popup: Codable {
let menuitem: [Menuitem]
}
// MARK: - Menuitem
struct Menuitem: Codable {
let value, onclick: String
}
/// Make Network Request
typealias RequestCompletionHandler<T: Decodable> = (_ value: T?, _ error: Error?) -> Void
func callAPI<T: Decodable>(completionHandler: RequestCompletionHandler<T>) {
let data = """
{"menu": {
"id": "file",
"value": "File",
"popup": {
"menuitem": [
{"value": "New", "onclick": "CreateNewDoc()"},
{"value": "Open", "onclick": "OpenDoc()"},
{"value": "Close", "onclick": "CloseDoc()"}
]
}
}}
""".data(using: .utf8)!
do {
let value = try JSONDecoder().decode(T.self, from: data)
completionHandler(value, nil)
} catch {
completionHandler(nil, error)
}
}
callAPI { (model: DemoJSON?, error) in
if let demoModel = model {
print("Success: \(demoModel)")
} else if let error = error {
print("Error: \(error)")
}
}
스위프트를 사용하셔도 됩니다.변환용 quicktype.ioJSON
어느 쪽이든struct
또는class
swift to generate 코드 버전도 언급할 수 있습니다.
예 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
}
}
SwiftyJ 사용방법SON 라이브러리, 이렇게 만들 수 있습니다.
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)
}
}
}
여기 더 단순하고 쉽게 만들 수 있는 샘플이 있습니다.데이터베이스의 My String 데이터는 다음과 같은 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 String에 대해 다음과 같이 String 확장자를 만듭니다.
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)
}}
셋째, 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()
}
swiftyJson 사용 스위프티 Json
platform :ios, '8.0'
use_frameworks!
target 'MyApp' do
pod 'SwiftyJSON', '~> 4.0'
end
사용.
import SwiftyJSON
let json = JSON(jsonObject)
let id = json["Id"].intValue
let name = json["Name"].stringValue
let lat = json["Latitude"].stringValue
let long = json["Longitude"].stringValue
let address = json["Address"].stringValue
print(id)
print(name)
print(lat)
print(long)
print(address)
언급URL : https://stackoverflow.com/questions/25621120/simple-and-clean-way-to-convert-json-string-to-object-in-swift
'programing' 카테고리의 다른 글
Node.js에 포맷된 JSON 쓰기 (0) | 2023.03.07 |
---|---|
배열의 항목 속성이 Json Schema에서 고유함을 확인하시겠습니까? (0) | 2023.03.07 |
Ajax 호출에서 워드프레스 함수를 사용하는 방법 (0) | 2023.03.07 |
반응 - 디버깅을 위해 DOM 요소에서 구성 요소를 가져옵니다. (0) | 2023.03.07 |
WordPress에서 홈페이지를 제외한 모든 페이지에 대해 404페이지를 찾을 수 없다고 합니다. (0) | 2023.03.07 |