Dies unter Klasse
class User: NSManagedObject {
@NSManaged var id: Int
@NSManaged var name: String
}
Muss konvertiert werden zu
{
"id" : 98,
"name" : "Jon Doe"
}
Ich habe versucht, das Objekt manuell an eine Funktion zu übergeben, die die Variablen in ein Wörterbuch setzt und das Wörterbuch zurückgibt. Aber ich würde einen besseren Weg wollen, um dies zu erreichen.
Antworten:
In Swift 4 können Sie von der erben
Codable
Typ .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)
quelle
class
(was ich brauche) nichtstruct
.Zusammen mit Swift 4 (Foundation) wird es jetzt auf beide Arten nativ unterstützt: JSON-Zeichenfolge für ein Objekt - ein Objekt für JSON-Zeichenfolge. Die Dokumentation von Apple finden Sie hier JSONDecoder () und hier JSONEncoder ()
JSON-String zum Objekt
let jsonData = jsonString.data(using: .utf8)! let decoder = JSONDecoder() let myStruct = try! decoder.decode(myStruct.self, from: jsonData)
Schnelles Objekt für JSONString
let encoder = JSONEncoder() encoder.outputFormatting = .prettyPrinted let data = try! encoder.encode(myStruct) print(String(data: data, encoding: .utf8)!)
Alle Details und Beispiele finden Sie hier Ultimate Guide to JSON Parsing With Swift 4
quelle
UPDATE: Das
Codable
in Swift 4 eingeführte Protokoll sollte für die meistenJSON
Parsing-Fälle ausreichend sein . Die folgende Antwort richtet sich an Personen, die in früheren Versionen von Swift und aus früheren Gründen nicht weiterkommenEVReflection :
NSDictionary
,NSCoding
,Printable
,Hashable
undEquatable
Beispiel:
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 :
Beispiel:
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)
quelle
Ich habe ein bisschen an einer kleineren Lösung gearbeitet, die keine Vererbung erfordert. Aber es wurde nicht viel getestet. Es ist ziemlich hässlich atm.
https://github.com/peheje/JsonSerializerSwift
Sie können es auf einen Spielplatz geben, um es zu testen. ZB folgende Klassenstruktur:
//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)
druckt
{"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"]}}
quelle
Dies ist keine perfekte / automatische Lösung, aber ich glaube, dies ist der idiomatische und native Weg, dies zu tun. Auf diese Weise benötigen Sie keine Bibliotheken oder ähnliches.
Erstellen Sie ein Protokoll wie:
/// 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) } }
Implementieren Sie es dann in Ihrer Klasse wie:
class User: JSONSerializable { var id: Int var name: String var dict { return ["id": self.id, "name": self.name] } }
Jetzt:
let user = User(...) let json = user.json()
Hinweis: Wenn Sie
json
eine Zeichenfolge verwenden möchten , können Sie diese ganz einfach in eine Zeichenfolge konvertieren:String(data: json, encoding .utf8)
quelle
Einige der obigen Antworten sind völlig in Ordnung, aber ich habe hier eine Erweiterung hinzugefügt, um sie besser lesbar und benutzerfreundlicher zu machen.
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!)
// Dies wird wie folgt gedruckt:
{ "id" : 1, "name" : "name" }
quelle
Ich bin mir nicht sicher, ob lib / framework existiert, aber ob du es automatisch machen möchtest und Handarbeit vermeiden möchtest :-) bleib bei
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 } }
Nehmen Sie es als grobes Beispiel, es fehlt die richtige Konvertierungsunterstützung, es fehlt die Rekursion, ... Es ist einfach
MirrorType
Demonstration ...PS Hier ist es erledigt
U
, aber Sie werden es verbessernNSManagedObject
und dann können Sie alleNSManagedObject
Unterklassen konvertieren . Dies muss nicht in allen Unterklassen / verwalteten Objekten implementiert werden.quelle
@NSManaged
. Vielleicht verursacht es Ihr Problem. In diesem Fall würde ich es in Objective-C schreiben und es dann von Swift verwenden.2020 | SWIFT 5.1:
(funktioniert auch mit SWIFT 4)
Arbeitsfertige Lösung!
Verwendung:
var msgTemplates = [msgTemlate]() // load from file msgTemplates = try! Serializer.load(from: url)! // save to file Serializer.save(data: msgTemplates, to: url)
Der folgende Code löst 3 Dinge:
element.toJsonString
import Foundation public class Serializer{ static func save<T>(data: T, to url: URL) where T : Encodable{ guard let json = data.toJsonString else { return } do { try json.write(to: url, atomically: true, encoding: String.Encoding.utf8) } catch { /* error handling here */ } } static func load<T>(from url: URL) throws -> T? where T : Decodable { let decoder = JSONDecoder() decoder.dateDecodingStrategy = .iso8601 // for human-read date format guard let dataStr = try? String(contentsOf: url, encoding: String.Encoding.utf8 ), let data = dataStr.data(using: String.Encoding.utf8 ), let result = try? decoder.decode( T.self , from: data) else { return nil } return result } } extension Encodable { var toJsonString: String? { let encoder = JSONEncoder() encoder.outputFormatting = .prettyPrinted // nice formatted for reading by human encoder.dateEncodingStrategy = .iso8601 // for human-read date format do { let jsonData = try encoder.encode(self) return String(data: jsonData, encoding: .utf8) } catch { return nil } } }
PS: und ofc Daten müssen codierbar sein:
struct msgTemlate: Codable { //some params }
PS2: Wenn msgTemlate Enums hat, müssen sie auch codierbar sein
quelle
struct User:Codable{ var id:String? var name:String? init(_ id:String,_ name:String){ self.id = id self.name = name } }
let user = User ("1", "pawan")
do{ let userJson = try JSONEncoder().encode(parentMessage) }catch{ fatalError("Unable To Convert in Json") }
let jsonDecoder = JSONDecoder() do{ let convertedUser = try jsonDecoder.decode(User.self, from: userJson.data(using: .utf8)!) }catch{ }
quelle