Подтвердить что ты не робот

Как сериализовать или преобразовать объекты Swift в JSON?

Это ниже класса

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

Необходимо преобразовать в

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

Я попытался вручную передать объект в функцию, которая устанавливает переменные в словарь и возвращает словарь. Но я бы хотел лучшего способа сделать это.

4b9b3361

Ответ 1

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

Ответ 2

ОБНОВЛЕНИЕ: Codable протокол, представленный в Swift 4, должен быть достаточным для большинства случаев анализа JSON. Ниже ответ для людей, которые застряли в предыдущих версиях Swift и по старым причинам

EVReflection :

  • Это работает принцип отражения. Это занимает меньше кода, а также поддерживает 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)

ObjectMapper :

  • Другой способ заключается в использовании ObjectMapper. Это дает больше контроля, но также требует намного больше кода.

Пример:

    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)

Ответ 3

Наряду с Swift 4 (Foundation) теперь поддерживается обеими способами: JSON-строка для объекта - объект для JSON-строки. Пожалуйста, смотрите документацию Apple здесь JSONDecoder() и здесь JSONEncoder()

Строка 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)!)

Вы можете найти все подробности и примеры здесь. Окончательное руководство по синтаксическому анализу JSON в Swift 4.

Ответ 4

Я немного поработал над меньшим решением, которое не требует наследования. Но это не было проверено много. Это довольно уродливый атм.

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

Ответ 5

Это не идеальное/автоматическое решение, но я считаю, что это идиоматический и родной способ сделать это. Таким образом, вам не нужны никакие библиотеки и т.д.

Создайте протокол, например:

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

Ответ 6

Не уверен, существует ли 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...

P.S. Здесь это делается в U, но вы улучшите NSManagedObject, а затем сможете конвертировать все подклассы NSManagedObject. Не нужно реализовывать это во всех подклассах/управляемых объектах.

Ответ 7

Этот пример кодирования в utf8.

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)

Ответ 8

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 = data: try JSONEncoder().encode(parentMessage), encoding:.utf8)

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

Затем преобразовать из JSON в объект

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

 }