这个下课
class User: NSManagedObject {
@NSManaged var id: Int
@NSManaged var name: String
}
需要转换为
{
"id" : 98,
"name" : "Jon Doe"
}
我尝试将对象手动传递给将变量设置为字典并返回字典的函数。但我希望有一种更好的方法来实现这一目标。
这个下课
class User: NSManagedObject {
@NSManaged var id: Int
@NSManaged var name: String
}
需要转换为
{
"id" : 98,
"name" : "Jon Doe"
}
我尝试将对象手动传递给将变量设置为字典并返回字典的函数。但我希望有一种更好的方法来实现这一目标。
Answers:
在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)
class
(我需要)不是struct
。
现在,与Swift 4(基础)一起都以两种方式原生支持它:对象的JSON字符串-对象为JSON字符串。请在此处JSONDecoder()和在此处JSONEncoder()参阅Apple的文档。
JSON字符串到对象
let jsonData = jsonString.data(using: .utf8)!
let decoder = JSONDecoder()
let myStruct = try! decoder.decode(myStruct.self, from: jsonData)
将对象转换为JSONString
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let data = try! encoder.encode(myStruct)
print(String(data: data, encoding: .utf8)!)
您可以在此处找到所有详细信息和示例,使用Swift 4进行JSON解析的终极指南。
更新: Codable
在大多数JSON
解析情况下,Swift 4中引入的协议就足够了。以下答案适用于因早期原因而停留在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)
例:
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是否存在,但是如果您想自动执行它并且希望避免体力劳动,请:-)坚持使用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
演示……
PS这是在中完成的U
,但是您将进行增强NSManagedObject
,然后就可以转换所有NSManagedObject
子类。无需在所有子类/托管对象中实现此功能。
@NSManaged
。可能是造成您的问题。在这种情况下,我将用Objective-C编写它,然后在Swift中使用它。
2020 | SWIFT 5.1:
(也适用于SWIFT 4)
准备工作解决方案!
用法:
var msgTemplates = [msgTemlate]()
// load from file
msgTemplates = try! Serializer.load(from: url)!
// save to file
Serializer.save(data: msgTemplates, to: url)
以下代码解决了三件事:
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:andofc数据必须是可编码的:
struct msgTemlate: Codable {
//some params
}
PS2:如果msgTemlate有枚举,则它们也必须是可编码的
struct User:Codable{
var id:String?
var name:String?
init(_ id:String,_ name:String){
self.id = id
self.name = name
}
}
现在只要像这样使你的物体
让用户= User(“ 1”,“ pawan”)
do{
let userJson = try JSONEncoder().encode(parentMessage)
}catch{
fatalError("Unable To Convert in Json")
}
然后从json转换为Object
let jsonDecoder = JSONDecoder()
do{
let convertedUser = try jsonDecoder.decode(User.self, from: userJson.data(using: .utf8)!)
}catch{
}