이 아래 수업
class User: NSManagedObject {
@NSManaged var id: Int
@NSManaged var name: String
}
변환해야합니다.
{
"id" : 98,
"name" : "Jon Doe"
}
변수를 사전에 설정하고 사전을 반환하는 함수에 객체를 수동으로 전달하려고했습니다. 그러나 나는 이것을 달성하는 더 나은 방법을 원할 것입니다.
답변
Swift 4에서는 Codable
유형 에서 상속 할 수 있습니다 .
struct Dog: Codable {
var name: String
var owner: String
}
// Encode
let dog = Dog(name: "Rex", owner: "Etgar")
let jsonEncoder = JSONEncoder()
let jsonData = try jsonEncoder.encode(dog)
let json = String(data: jsonData, encoding: String.Encoding.utf16)
// Decode
let jsonDecoder = JSONDecoder()
let secondDog = try jsonDecoder.decode(Dog.self, from: jsonData)
답변
이제 Swift 4 (Foundation)와 함께 기본적으로 두 가지 방식으로 지원됩니다. JSON 문자열에서 객체로, 객체에서 JSON 문자열로. 여기에서 Apple의 설명서를 참조하십시오. JSONDecoder () 및 여기 JSONEncoder ()
객체에 대한 JSON 문자열
let jsonData = jsonString.data(using: .utf8)!
let decoder = JSONDecoder()
let myStruct = try! decoder.decode(myStruct.self, from: jsonData)
JSONString에 대한 Swift 객체
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let data = try! encoder.encode(myStruct)
print(String(data: data, encoding: .utf8)!)
여기에서 모든 세부 정보와 예제를 찾을 수 있습니다. Swift 4를 사용한 JSON 구문 분석에 대한 궁극적 인 가이드
답변
업데이트 : Codable
Swift 4에 도입 된 프로토콜은 대부분의 JSON
구문 분석 사례에 충분합니다 . 아래 답변은 이전 버전의 Swift와 레거시 이유로 인해 갇혀있는 사람들을위한 것입니다.
- 이것은 반사 원리의 작품입니다. 이것은 또한 적은 코드를 받아 지원
NSDictionary
,NSCoding
,Printable
,Hashable
및Equatable
예:
class User: EVObject { # extend EVObject method for the class
var id: Int = 0
var name: String = ""
var friends: [User]? = []
}
# use like below
let json:String = "{\"id\": 24, \"name\": \"Bob Jefferson\", \"friends\": [{\"id\": 29, \"name\": \"Jen Jackson\"}]}"
let user = User(json: json)
- 또 다른 방법은 ObjectMapper를 사용하는 것입니다. 이것은 더 많은 제어를 제공하지만 더 많은 코드를 필요로합니다.
예:
class User: Mappable { # extend Mappable method for the class
var id: Int?
var name: String?
required init?(_ map: Map) {
}
func mapping(map: Map) { # write mapping code
name <- map["name"]
id <- map["id"]
}
}
# use like below
let json:String = "{\"id\": 24, \"name\": \"Bob Jefferson\", \"friends\": [{\"id\": 29, \"name\": \"Jen Jackson\"}]}"
let user = Mapper<User>().map(json)
답변
상속이 필요하지 않은 더 작은 솔루션에 대해 약간 작업했습니다. 그러나 그것은 많이 테스트되지 않았습니다. 꽤 못생긴 ATM입니다.
https://github.com/peheje/JsonSerializerSwift
그것을 테스트하기 위해 놀이터로 전달할 수 있습니다. 예 : 다음 클래스 구조 :
//Test nonsense data
class Nutrient {
var name = "VitaminD"
var amountUg = 4.2
var intArray = [1, 5, 9]
var stringArray = ["nutrients", "are", "important"]
}
class Fruit {
var name: String = "Apple"
var color: String? = nil
var weight: Double = 2.1
var diameter: Float = 4.3
var radius: Double? = nil
var isDelicious: Bool = true
var isRound: Bool? = nil
var nullString: String? = nil
var date = NSDate()
var optionalIntArray: Array<Int?> = [1, 5, 3, 4, nil, 6]
var doubleArray: Array<Double?> = [nil, 2.2, 3.3, 4.4]
var stringArray: Array<String> = ["one", "two", "three", "four"]
var optionalArray: Array<Int> = [2, 4, 1]
var nutrient = Nutrient()
}
var fruit = Fruit()
var json = JSONSerializer.toJson(fruit)
print(json)
인쇄물
{"name": "Apple", "color": null, "weight": 2.1, "diameter": 4.3, "radius": null, "isDelicious": true, "isRound": null, "nullString": null, "date": "2015-06-19 22:39:20 +0000", "optionalIntArray": [1, 5, 3, 4, null, 6], "doubleArray": [null, 2.2, 3.3, 4.4], "stringArray": ["one", "two", "three", "four"], "optionalArray": [2, 4, 1], "nutrient": {"name": "VitaminD", "amountUg": 4.2, "intArray": [1, 5, 9], "stringArray": ["nutrients", "are", "important"]}}
답변
이것은 완벽한 / 자동 솔루션은 아니지만 이것이 관용적이고 고유 한 방법 이라고 생각합니다 . 이렇게하면 라이브러리 등이 필요하지 않습니다.
다음과 같은 프로토콜을 만듭니다.
/// A generic protocol for creating objects which can be converted to JSON
protocol JSONSerializable {
private var dict: [String: Any] { get }
}
extension JSONSerializable {
/// Converts a JSONSerializable conforming class to a JSON object.
func json() rethrows -> Data {
try JSONSerialization.data(withJSONObject: self.dict, options: nil)
}
}
그런 다음 다음과 같이 클래스에서 구현하십시오.
class User: JSONSerializable {
var id: Int
var name: String
var dict { return ["id": self.id, "name": self.name] }
}
지금:
let user = User(...)
let json = user.json()
참고 : json
문자열로 원하는 경우 문자열로 변환하는 것은 매우 간단합니다.String(data: json, encoding .utf8)
답변
위의 답변 중 일부는 완전히 괜찮지 만 훨씬 더 읽기 쉽고 사용 가능하도록 여기에 확장 기능을 추가했습니다.
extension Encodable {
var convertToString: String? {
let jsonEncoder = JSONEncoder()
jsonEncoder.outputFormatting = .prettyPrinted
do {
let jsonData = try jsonEncoder.encode(self)
return String(data: jsonData, encoding: .utf8)
} catch {
return nil
}
}
}
struct User: Codable {
var id: Int
var name: String
}
let user = User(id: 1, name: "name")
print(user.convertToString!)
// 다음과 같이 인쇄됩니다.
{
"id" : 1,
"name" : "name"
}
답변
lib / framework가 있는지 확실하지 않지만 자동으로 수행하고 수동 작업을 피하고 싶다면 🙂 stick with MirrorType
…
class U {
var id: Int
var name: String
init(id: Int, name: String) {
self.id = id
self.name = name
}
}
extension U {
func JSONDictionary() -> Dictionary<String, Any> {
var dict = Dictionary<String, Any>()
let mirror = reflect(self)
var i: Int
for i = 0 ; i < mirror.count ; i++ {
let (childName, childMirror) = mirror[i]
// Just an example how to check type
if childMirror.valueType is String.Type {
dict[childName] = childMirror.value
} else if childMirror.valueType is Int.Type {
// Convert to NSNumber for example
dict[childName] = childMirror.value
}
}
return dict
}
}
대략적인 예를 들어, 적절한 변환 지원이 부족하고, 재귀가 부족합니다. … 단지 MirrorType
데모 일뿐입니다 .
추신 여기에서는에서 완료 U
되었지만 향상시키고 NSManagedObject
모든 NSManagedObject
하위 클래스 를 변환 할 수 있습니다 . 모든 서브 클래스 / 관리 객체에서이를 구현할 필요가 없습니다.