Swift 개체를 사전으로 변환하는 방법
iOS 프로그래밍은 비교적 초보입니다.단, Swift는 오브젝트를 JSON으로 자동 변환하는 방법을 가지고 있을 것으로 생각됩니다.그러나, 나는 이것을 할 수 있는 라이브러리를 몇 개 찾았습니다.
하지만...
웹 서비스에 데이터를 어떻게 게시하든(Alamo Fire 같은 것을 사용해도) 사전이 요구되어야 하는 것 같습니다.이러한 포럼에서는 반환된 JSON 문자열을 개체로 쉽게 변환할 수 있음을 보여 줍니다.맞아요, 하지만 요청은 수동으로 코딩해야 해요즉, 모든 개체 속성을 살펴보고 사전으로 매핑합니다.
제 질문은 다음과 같습니다.내가 뭘 빼놓았나요?제가 잘못 알고 있는 건가요? (a) REQUEST에서 (사전 대신) JSON을 전송하거나 (b) 객체를 사전으로 자동 변환하는 매우 쉬운 방법이 있나요?
JSON 응답에 대처하는 것이 얼마나 쉬운지 알 수 있습니다.웹 서비스에 게시할 요청 개체를 Alamo Fire와 같은 라이브러리에 필요한 형식으로 자동 변환하는 방법을 찾고 있습니다.다른 언어에서는 이것은 매우 사소한 일이기 때문에 Swift에서도 마찬가지로 쉽고 자동화된 방법이 있었으면 합니다.
@Darko의 의견에 동의하지 않을 수 없습니다.
Swift 2에서는
프로토콜 지향 프로그래밍과 Mirror 클래스에서 제공하는 단순 리플렉션을 사용합니다.
protocol JSONAble {}
extension JSONAble {
func toDict() -> [String:Any] {
var dict = [String:Any]()
let otherSelf = Mirror(reflecting: self)
for child in otherSelf.children {
if let key = child.label {
dict[key] = child.value
}
}
return dict
}
}
그러면 이 프로토콜을 요청 클래스와 함께 사용하여 원하는 사전을 만들 수 있습니다.
class JsonRequest : JSONAble {
var param1 : String?
// ...
}
let request = JsonRequest()
// set params of the request
let dict = request.toDict()
// use your dict
이에 대한 저의 해결책은 다음과 같습니다.
extension Encodable {
var dict : [String: Any]? {
guard let data = try? JSONEncoder().encode(self) else { return nil }
guard let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String:Any] else { return nil }
return json
}
}
용도는 다음과 같습니다.
movies.compactMap { $0.dict }
Swift는 현재 Java나 C#과 같은 고급 리플렉션을 지원하지 않기 때문에 정답은 다음과 같습니다. 즉, 순수 Swift에는 똑같이 쉽고 자동화된 방법이 없습니다.
[갱신] 스위프트4는 그동안Codable
JSON 및 PLIST와의 시리얼화를 허용하는 프로토콜입니다.
typealias Codable = Decodable & Encodable
반사를 사용하지 않고 중첩된 객체에 대해 작동합니다(Swift 4).
protocol Serializable {
var properties:Array<String> { get }
func valueForKey(key: String) -> Any?
func toDictionary() -> [String:Any]
}
extension Serializable {
func toDictionary() -> [String:Any] {
var dict:[String:Any] = [:]
for prop in self.properties {
if let val = self.valueForKey(key: prop) as? String {
dict[prop] = val
} else if let val = self.valueForKey(key: prop) as? Int {
dict[prop] = val
} else if let val = self.valueForKey(key: prop) as? Double {
dict[prop] = val
} else if let val = self.valueForKey(key: prop) as? Array<String> {
dict[prop] = val
} else if let val = self.valueForKey(key: prop) as? Serializable {
dict[prop] = val.toDictionary()
} else if let val = self.valueForKey(key: prop) as? Array<Serializable> {
var arr = Array<[String:Any]>()
for item in (val as Array<Serializable>) {
arr.append(item.toDictionary())
}
dict[prop] = arr
}
}
return dict
}
}
변환할 사용자 지정 개체에 대한 속성 및 valueForKey를 구현하기만 하면 됩니다.예를 들어 다음과 같습니다.
class Question {
let title:String
let answer:Int
init(title:String, answer:Int) {
self.title = title
self.answer = answer
}
}
extension Question : Serializable {
var properties: Array<String> {
return ["title", "answer"]
}
func valueForKey(key: String) -> Any? {
switch key {
case "title":
return title
case "answer":
return answer
default:
return nil
}
}
}
필요에 따라 toDictionary 함수에 값 유형을 추가할 수 있습니다.
Stack Overflow를 여러 번 조사한 결과 발견한 최신 솔루션은 다음과 같습니다.
//This block of code used to convert object models to json string
let jsonData = try JSONEncoder().encode(requestData)
let jsonString = String(data: jsonData, encoding: .utf8)!
print(jsonString)
//This method is used to convert jsonstring to dictionary [String:Any]
func jsonToDictionary(from text: String) -> [String: Any]? {
guard let data = text.data(using: .utf8) else { return nil }
let anyResult = try? JSONSerialization.jsonObject(with: data, options: [])
return anyResult as? [String: Any]
}
//Use above method something like this
let params = jsonToDictionary(from: jsonString) ?? [String : Any]()
//Use params to pass in paramters
Alamofire.request(completeUrl, method: .post, parameters: params, encoding:JSONEncoding.prettyPrinted, headers: myHeaders){
response in
//Do whatever you want with response of it.
}
주의:
- 저는 이 솔루션을 여러 답변에서 조합합니다.
- 이 솔루션은 alamofire가 이 형식의 파라미터만 받아들이기 때문에 alamofire와 함께 사용하였습니다.(String:[임의]).
ObjectMapper 라이브러리를 사용할 수도 있습니다.오브젝트를 사전으로 변환하는 "toJSON" 메서드가 있습니다.
요컨대
let dict = Mirror(reflecting: self).children.map({ $0 }).reduce(into: [:]) { $0[$1.label] = $1.value }
미러를 특정 사전 유형으로 변환하여 사용하는 예:
protocol DictionaryConvertible { }
extension DictionaryConvertible {
func toDictionary() -> [String: CustomStringConvertible] {
Dictionary(
uniqueKeysWithValues: Mirror(reflecting: self).children
.compactMap { child in
if let label = child.label,
let value = child.value as? CustomStringConvertible {
return (label, value)
} else {
return nil
}
}
)
}
}
언급URL : https://stackoverflow.com/questions/31971256/how-to-convert-a-swift-object-to-a-dictionary
'programing' 카테고리의 다른 글
Word press POST인지 PAGE인지 확인하는 방법 (0) | 2023.02.27 |
---|---|
Python에서 JSON을 XML로 변환 (0) | 2023.02.27 |
Spring Boot에서 Error Page Filter를 비활성화하려면 어떻게 해야 합니까? (0) | 2023.02.27 |
Wordpress에서 현지화된 스크립트의 Data 매개 변수 업데이트 (0) | 2023.02.27 |
sql ignoring 대소문자의 문자열을 비교하는 방법 (0) | 2023.02.27 |