如何将 Swift 对象序列化或转换为 JSON?

这是课下的东西

class User: NSManagedObject {
@NSManaged var id: Int
@NSManaged var name: String
}

需要转换为

{
"id" : 98,
"name" : "Jon Doe"
}

我尝试手动将对象传递给一个函数,该函数将变量设置为 dictionary 并返回 dictionary。但是我想要一个更好的方法来完成这个任务。

139998 次浏览

不确定是否存在 lib/框架,但是如果您希望自动执行它,并且希望避免手工操作: ——坚持使用 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子类。不需要在所有子类/托管对象中实现这一点。

UPDATE: Codable protocol introduced in Swift 4 should be sufficient for most of the JSON parsing cases. Below answer is for people who are stuck in previous versions of Swift and for legacy reasons

EVReflection :

  • 这种工作原理的反射。这需要较少的代码,也支持 NSDictionaryNSCodingPrintableHashableEquatable

例如:

    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 :

  • 另一种方法是使用 ObjectMapper。

Example:

    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)

我致力于一个不需要继承的小型解决方案。但还没有经过多少测试。自动取款机真难看。

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)

在 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 字符串。 请参阅苹果公司的文档(https://www.google.com.tr/url? sa = t & amp; rct = j & amp; q = & amp; esrc = s & amp; source = web & amp; cd = 3 & amp; cad = rja & amp; uact = 8 & ved = 0ahUKEwj654zqrt _ WAhWFO5oKHRwaD-8QFggzMAI & amp; url = https% 3A% 2F% 2Fdeveloper.Apple.com% 2Fdocument% 2Fjsonencoder & amp; usg = AOVVaw2-O8e-qf9HdihmrOVpzKO-”rel = “ noReferrer”> JSONEncoder ())

对象字符串

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 的终极指南

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")
}

然后从 json 重新转换为 Object

let jsonDecoder = JSONDecoder()
do{
let convertedUser = try jsonDecoder.decode(User.self, from: userJson.data(using: .utf8)!)
}catch{
   

}

上面的一些答案完全没问题,但是我在这里添加了一个扩展,只是为了使它更具可读性和可用性。

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"
}

2021 | SWIFT 5.1 | Results Solution 2021 | SWIFT 5.1 | 结果解决方案

输入数据:

struct ConfigCreds: Codable {
// some params
}

用途:

// get JSON from Object
configCreds
.asJson()
.onSuccess{ varToSaveJson = $0 }
.onFailure{ _ in // any failure code }


// get object of type "ConfigCreds" from JSON
someJsonString
.decodeFromJson(type: ConfigCreds.self)
.onSuccess { configCreds = $0 }
.onFailure{ _ in // any failure code }

返回代码:

@available(macOS 10.15, *)
public extension Encodable {
func asJson() -> Result<String, Error>{
JSONEncoder()
.try(self)
.flatMap{ $0.asString() }
}
}


public extension String {
func decodeFromJson<T>(type: T.Type) -> Result<T, Error> where T: Decodable {
self.asData()
.flatMap { JSONDecoder().try(type, from: $0) }
}
}


///////////////////////////////
/// HELPERS
//////////////////////////////


@available(macOS 10.15, *)
fileprivate extension JSONEncoder {
func `try`<T : Encodable>(_ value: T) -> Result<Output, Error> {
do {
return .success(try self.encode(value))
} catch {
return .failure(error)
}
}
}


fileprivate extension JSONDecoder {
func `try`<T: Decodable>(_ t: T.Type, from data: Data) -> Result<T,Error> {
do {
return .success(try self.decode(t, from: data))
} catch {
return .failure(error)
}
}
}


fileprivate extension String {
func asData() -> Result<Data, Error> {
if let data = self.data(using: .utf8) {
return .success(data)
} else {
return .failure(WTF("can't convert string to data: \(self)"))
}
}
}


fileprivate extension Data {
func asString() -> Result<String, Error> {
if let str = String(data: self, encoding: .utf8) {
return .success(str)
} else {
return .failure(WTF("can't convert Data to string"))
}
}
}


fileprivate func WTF(_ msg: String, code: Int = 0) -> Error {
NSError(code: code, message: msg)
}