Bagaimana untuk membuat atau mengkonversi Swift objek JSON?

Di bawah ini kelas

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

Perlu dikonversi ke

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

Saya mencoba secara manual lewat objek untuk fungsi yang menetapkan variabel-variabel ke dalam sebuah kamus dan pengembalian kamus. Tapi aku akan ingin cara yang lebih baik untuk mencapai hal ini.

Mengomentari pertanyaan (7)
Larutan

Di Swift 4, anda dapat mewarisi dari Codable jenis.

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 dog = try jsonDecoder.decode(Dog.self, from: jsonData)
Komentar (7)

Selain Swift 4 (Foundation) sekarang itu adalah native didukung di kedua cara, JSON string ke objek - objek JSON string. Silahkan lihat Apple's dokumentasi di sini JSONDecoder() dan di sini JSONEncoder()

String JSON ke Object

let jsonData = jsonString.data(using: .utf8)!
let decoder = JSONDecoder()
let myStruct = try! decoder.decode(myStruct.self, from: jsonData)

Swift Objek untuk JSONString

let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let data = try! encoder.encode(myStruct)
print(String(data: data, encoding: .utf8)!)

Anda dapat menemukan semua rincian dan contoh-contoh berikut ini Panduan Ultimate untuk Parsing JSON Dengan Cepat 4

Komentar (0)

UPDATE: Codable protokol diperkenalkan di Swift 4 harus cukup untuk sebagian besar JSON parsing kasus. Di bawah ini jawabannya adalah untuk orang-orang yang terjebak di versi sebelumnya dari Swift dan untuk alasan warisan

[EVReflection][1] :

  • Ini bekerja dari prinsip refleksi. Ini membutuhkan waktu kurang code dan juga mendukung NSDictionary, majic jungle software, Dicetak, Hashable dan Equatable

Contoh:

    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][2] :

  • Cara lain adalah dengan menggunakan ObjectMapper. Hal ini memberikan lebih banyak kontrol, tetapi juga membutuhkan lebih banyak kode.

Contoh:


    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    
Komentar (5)

Saya bekerja sedikit lebih kecil solusi yang doesn't membutuhkan warisan. Tapi itu belum't telah diuji banyak. It's cukup jelek atm.

https://github.com/peheje/JsonSerializerSwift

Anda dapat lulus ke sebuah taman bermain untuk menguji itu. E. g. berikut struktur kelas:

//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 = [1, 5, 3, 4, nil, 6]
    var doubleArray: Array = [nil, 2.2, 3.3, 4.4]
    var stringArray: Array = ["one", "two", "three", "four"]
    var optionalArray: Array = [2, 4, 1]

    var nutrient = Nutrient()
}

var fruit = Fruit()
var json = JSONSerializer.toJson(fruit)

print(json)

cetakan

{"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"]}}
Komentar (1)

Ini bukan pilihan/solusi otomatis tapi saya percaya ini adalah idiomatic dan asli cara untuk melakukan hal tersebut. Dengan cara ini anda don't perlu setiap perpustakaan atau seperti.

Membuat sebuah protokol seperti:

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

Kemudian menerapkannya di kelas anda seperti:

class User: JSONSerializable {
    var id: Int
    var name: String

    var dict { return ["id": self.id, "name": self.name]  }
}

Sekarang:

let user = User(...)
let json = user.json()

Catatan: jika anda ingin json sebagai string, hal ini sangat sederhana untuk mengkonversi string: String(data: json, encoding .utf8)

Komentar (0)

Beberapa hal di atas jawaban yang benar-benar baik-baik saja, tapi aku menambahkan ekstensi di sini, hanya untuk membuatnya lebih mudah dibaca dan digunakan.

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!)

//Cetak ini akan seperti berikut:

{
  "id" : 1,
  "name" : "name"
}
Komentar (0)

Tidak yakin jika lib/framework yang ada, tapi jika anda ingin melakukannya secara otomatis dan anda akan ingin menghindari tenaga kerja manual :-) tetap dengan 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 {
    var dict = Dictionary()

    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
  }

}

Menganggapnya sebagai kasar contoh, kurang tepat konversi dukungan, kekurangan rekursi, ... Itu's hanya MirrorType demonstrasi ...

P. S. Berikut ini's dilakukan di U, tapi anda're akan meningkatkan NSManagedObject dan kemudian anda'akan dapat mengkonversi semua NSManagedObject subclass. Tidak perlu untuk menerapkan ini dalam semua subclass/dikelola benda-benda.

Komentar (2)
struct User:Codable{
 var id:String?
 var name:String?
 init(_ id:String,_ name:String){
   self.id  = id
   self.name = name
 }
}

Sekarang hanya membuat objek anda seperti ini

biarkan user = user("1","pawan")

do{
      let userJson = data: try JSONEncoder().encode(parentMessage), encoding:.utf8)

    }catch{
         fatalError("Unable To Convert in Json")      
    }

Kemudian reconvert dari json ke Object

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

 }
Komentar (0)