Swift nesneleri JSON'a nasıl serileştirilir veya dönüştürülür?

Bu sınıfın altında

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

Dönüştürülmesi gerekenler

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

Nesneyi, değişkenleri bir sözlüğe ayarlayan ve sözlüğü döndüren bir işleve el ile geçirmeyi denedim. Ama bunu başarmak için daha iyi bir yol istiyorum.

38
En iyi şansınız, üzerinden geçmek ve dizilere ve dikmelere kaydetmek, sonra dönüştürmektir.
katma yazar Schemetrical, kaynak
Nesnenin içinden geçmeniz, tüm değerleri almanız ve onu bir dikime manuel olarak eklemeniz ve tekrarlamanız gerekir.
katma yazar Schemetrical, kaynak
@ redo1135 kodunuzla bile ne yapıyorsunuz? Derleme zamanı dramatik bir şekilde artmamalı, ne yaptığını bilmiyorum derleme süresini artıracak.
katma yazar Schemetrical, kaynak
@Chemetrical bana bir örnek gösterebilir misiniz? Bir nesneyi nasıl geçireceğimi bilmiyorum.
katma yazar Penkey Suresh, kaynak
@Chemetrical Aslında bunu denedim. Ancak büyük nesneler için derleme zamanı çarpıcı biçimde artar.
katma yazar Penkey Suresh, kaynak
@Schemetrical API'ye bir nesne göndermeye çalışıyorum. Nesne 21 değer içeriyor. Sorumu, kullandığım işlevi içerecek şekilde güncelledim. Lütfen herhangi bir iyileştirme/öneri bildiriniz.
katma yazar Penkey Suresh, kaynak
katma yazar Uttam Sinha, kaynak

7 cevap

Hızlı 4'te, Codable türünden miras alabilirsiniz.

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)
35
katma
Bu özel örnek için .utf16 çalışıyor mu? Denedim ama işe yaramadı.
katma yazar Chan Jing Hong, kaynak
Kodlama türü .utf16 yerine .utf8 olmalıdır
katma yazar Chan Jing Hong, kaynak
Çeşitli türde bir seri nesneniz varsa ne olur? Hepsi Codable hariç, türler hakkında çok fazla bilginiz yok. Bu durumu ele almanın bir yolu var mı?
katma yazar Alexander Smith, kaynak
@ChanJingBu kodlamaya çalıştığınız şeye bağlıdır
katma yazar Etgar, kaynak
@ChanJingHong Garip, 3 ay önce denedim ve işe yaradı. Kodlama türünü de kod çözme yönteminde bir argüman olarak koymam gerektiğini düşünüyorum. Kontrol edeceğim.
katma yazar Etgar, kaynak

EVReflection :

  • This works of reflection principle. This takes less code and also supports NSDictionary, NSCoding, Printable, Hashable and Equatable

Örnek:

    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 :

  • Başka bir yol ise ObjectMapper kullanmaktır. Bu daha fazla kontrol sağlar ancak aynı zamanda daha fazla kod alır.

Örnek:

    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().map(json)

Note: For upto date library support for JSON check out this awesome list of Swift

22
katma
Merhaba, Mappable sınıfını nasıl başlatacağınızı ve özellikleri elle ayarlayıp nesneyi jsonString'e nasıl dönüştürebileceğinizi biliyor musunuz?
katma yazar VAAA, kaynak
@Charlie üzgünüm bu mümkün olup olmadığından emin değilim.
katma yazar Penkey Suresh, kaynak
@ Suresh: Özel dönüşüm gösterilen örneklerle yazılarak mümkündür. Görüntüyü String'e çevirip Json nesnesine ekledim. Özellikle saat os ile çalışan bir çok yardımcı olur
katma yazar Charlie, kaynak
Ayrıca görüntüleri eşleme destekliyor mu?
katma yazar Charlie, kaynak
kodlanabilir protokolün hızlı 4/ios 11'den etkisi nedir? . Bunu kullanarak NSManagedObject'i hızlıca 4'te JSON'a dönüştürebilir miyiz?
katma yazar user1828845, kaynak

Miras gerektirmeyen daha küçük bir çözüm üzerinde biraz çalıştım. Ancak çok fazla test edilmedi. Oldukça çirkin bir atm.

https://github.com/peheje/JsonSerializerSwift

Test etmek için bir oyun alanına sokabilirsiniz. Örneğin. aşağıdaki sınıf yapı:

//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 = ["one", "two", "three", "four"]
    var optionalArray: Array = [2, 4, 1]

    var nutrient = Nutrient()
}

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

print(json)

baskılar

{"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"]}}
13
katma
onun hızlı 2.3 sürümünü sağlayabilir misiniz?
katma yazar H Raval, kaynak

Along with Swift 4 (Foundation) now it is natively supported in both ways, JSON string to an object - an object to JSON string. Please see Apple's documentation here JSONDecoder() and here JSONEncoder()

JSON Dize Nesnesine

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

JSONString için Hızlı Nesne

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

You can find all details and examples here Ultimate Guide to JSON Parsing With Swift 4

13
katma

Bu mükemmel/otomatik bir çözüm değil, bunun aptal ve yerli yol olduğuna inanıyorum. Bu şekilde hiçbir kütüphaneye veya benzeri bir şeye ihtiyacınız yoktur.

Gibi bir protokol oluşturun:

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

Ardından aşağıdaki gibi sınıfınıza uygulayın:

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

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

Şimdi:

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

Note: if you want json as a string, it is very simply to convert to a string: String(data: json, encoding .utf8)

5
katma

Lib/framework var olup olmadığından emin değilsiniz, ancak otomatik olarak yapmak istiyorsanız ve el emeğinden kaçınmak istiyorsanız :-) 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
  }

}

Kaba bir örnek olarak kabul edin, uygun dönüştürme desteğinden yoksun, özyinelemeden yoksun, ... Sadece MirrorType gösterimi ...

Not; Burada U 'da yapılır, ancak NSManagedObject ' ı geliştireceksiniz ve ardından tüm NSManagedObject alt sınıflarını dönüştürebileceksiniz. Bunu tüm alt sınıflarda/yönetilen nesnelerde uygulamanıza gerek yok.

2
katma
Merhaba, bu yöntemi deniyorum, ama her seferinde 0 olarak sayıyorum. Ne yapmam gerektiği konusunda daha spesifik olabilir misiniz? @NSManaged'in sorunlara neden olduğunu düşünüyorum. NSManagedObject'i nasıl geliştiririm?
katma yazar Penkey Suresh, kaynak
@NSManaged ile denemedi. Belki de bu senin soruna neden oluyor. Bu durumda, bunu Objective-C'ye yazacağım ve Swift'den kullanacağım.
katma yazar robertvojta, kaynak

Bu örnek utf8’de kodlama yapar.

struct Person: Codable {
    var name: String
    var id: Int
}

   //Encode
    let p = Person(name: "test", id: 1)
    let jsonEncoder = JSONEncoder()
    do {
        let jsonData = try jsonEncoder.encode(p)
        let jsonString = String(data: jsonData, encoding: .utf8)
        print("JSON String : " + jsonString!)
    }
    catch {
        print("error")
    }

   //Decode
    let jsonDecoder = JSONDecoder()
    let person = try jsonDecoder.decode(Person.self, from: jsonString)
0
katma