Je dois "répliquer" une entrée renvoyée par un service API Web distant en JSON. Cela ressemble à ceci:
{
"field1": "some_id",
"entity_name" = "Entity1"
"field2": "some name",
"details1": [{
"field1": 11,
"field2": "some value",
"data": {
"key1": "value1",
"key2": "value2",
"key3": "value3",
// any other, unknown at compile time keys
}
}],
"details2": {
"field1": 13,
"field2": "some value2"
}
}
Voici ma tentative:
struct Entity1 {
struct Details1 {
let field1: UInt32
let field2: String
let data: [String: String]
}
struct Details2 {
let field1: UInt32
let field2: String
}
let field1: String
static let entityName = "Entity1"
let field2: String
let details1: [Details1]
let details2: Details2
}
Comme ça:
//doesn't compile
struct Entity1 {
let details1: [Details1 {
let field1: UInt32
let field2: String
let data: [String: String]
}]
Vous pouvez utiliser l'une quelconque des bonnes bibliothèques disponibles ci-dessous pour gérer le mappage de JSON à Object dans Swift:
Chacun a un bon tutoriel pour les débutants.
En ce qui concerne le thème struct
ou class
, vous pouvez considérer le texte suivant tiré de Le langage de programmation Swift documentation:
Les instances de structure sont toujours passées par valeur et les instances de classe Sont toujours passées par référence. Cela signifie qu'ils sont Adaptés à différents types de tâches. Lorsque vous considérez les constructions de données Et les fonctionnalités dont vous avez besoin pour un projet, décidez Si chaque construction de données doit être définie en tant que classe ou en tant que structure.
En règle générale, envisagez de créer une structure lorsqu'un ou plusieurs De ces conditions s'appliquent:
- L’objectif principal de la structure est d’encapsuler quelques valeurs de données relativement simples.
- Il est raisonnable de s’attendre à ce que les valeurs encapsulées soient copiées plutôt que référencées lorsque vous affectez ou transmettez une instance De cette structure.
- Toutes les propriétés stockées par la structure sont elles-mêmes des types de valeur, qui devraient également être copiées plutôt que référencées.
- La structure n'a pas besoin d'hériter des propriétés ou du comportement d'un autre type existant.
Voici des exemples de bons candidats pour les structures:
- La taille d'une forme géométrique, encapsulant peut-être une propriété width et une propriété height, toutes deux de type Double.
- Un moyen de faire référence à des plages dans une série, encapsulant éventuellement une propriété de départ et une propriété de longueur, de type Int.
- Un point dans un système de coordonnées 3D, encapsulant éventuellement des propriétés x, y et z, chacune de type Double.
Dans tous les autres cas, définissez une classe et créez des instances de cette classe À gérer et à transmettre par référence. En pratique, cela signifie que La plupart des structures de données personnalisées doivent être des classes et non des structures.
J'espère que cela vous aidera.
HandyJSON
est exactement ce dont vous avez besoin. Voir exemple de code:
struct Animal: HandyJSON { nom de la variable: String? var id: Chaîne? var num: Int? } let jsonString = "{\" name\": \" cat\", \" id\": \" 12345\", \" num\": 180}" si animal = JSONDeserializer.deserializeFrom (json: jsonString) { empreinte (animal) }
Obtenez les résultats de la recherche iTunes avec API de recherche iTunes avec une simple requête https://iTunes.Apple.com/search?term=jack+johnson
Podfile
platform :ios, '8.0'
use_frameworks!
target 'stackoverflow-29749652' do
pod 'Alamofire'
pod 'ObjectMapper'
end
classe NetworkManager
import Foundation
import Alamofire
// data loader
class NetworkManager {
class func request(string: String, block: @escaping ([String: Any]?)->()) {
Alamofire.request(string).responseJSON { response in
// print(response.request) // original URL request
// print(response.response) // HTTP URL response
// print(response.data) // server data
// print(response.result) // result of response serialization
if let result = response.result.value as? [String: Any] {
block(result)
} else {
block(nil)
}
}
}
}
classe ItunceItem (mappage)
import Foundation
import ObjectMapper
class ItunceItem: Mappable {
var wrapperType: String?
var artistId:Int?
var trackName:String?
var trackPrice: Double?
var currency:String?
required convenience init?(map: Map) {
self.init()
}
private func unwrapedDescription(value: Any?) -> String {
if let value = value {
return "\(value)"
}
return "[no data]"
}
var description: String {
var _result = " trackName: \(unwrapedDescription(value: trackName))\n"
_result += " artistId: \(unwrapedDescription(value: artistId))\n"
_result += " wrapperType: \(unwrapedDescription(value: wrapperType))\n"
_result += " price: "
if let trackPrice = self.trackPrice, let currency = self.currency {
_result += "\(trackPrice) \(currency)\n"
} else {
_result += "[no data]"
}
return _result
}
func mapping(map: Map) {
trackName <- map["trackName"]
artistId <- map["artistId"]
wrapperType <- map["wrapperType"]
trackPrice <- map["trackPrice"]
currency <- map["currency"]
}
}
NetworkManager.request(string: "https://iTunes.Apple.com/search?term=jack+johnson") { json in
if let json = json, let array = json["results"] as? [[String:Any]] {
for item in array {
if let itunceItem = ItunceItem(JSON: item) {
print("----------------------------------------------")
print(itunceItem.description)
}
}
}
}
Jetez un coup d'œil à cette superbe bibliothèque qui répond parfaitement à vos besoins, Argo sur GitHub .
Dans votre cas, un struct est ok. Vous pouvez en savoir plus sur le choix entre une structure et une classe ici .
vous pouvez utiliser SwiftyJson et let json = JSONValue(dataFromNetworking)
if let userName = json[0]["user"]["name"].string{
//Now you got your value
}
Vous pouvez aller avec cette extension pour Alamofire https://github.com/sua8051/AlamofireMapper
Déclarez une classe ou une structure:
class UserResponse: Decodable {
var page: Int!
var per_page: Int!
var total: Int!
var total_pages: Int!
var data: [User]?
}
class User: Decodable {
var id: Double!
var first_name: String!
var last_name: String!
var avatar: String!
}
Utilisation:
import Alamofire
import AlamofireMapper
let url1 = "https://raw.githubusercontent.com/sua8051/AlamofireMapper/master/user1.json"
Alamofire.request(url1, method: .get
, parameters: nil, encoding: URLEncoding.default, headers: nil).responseObject { (response: DataResponse<UserResponse>) in
switch response.result {
case let .success(data):
dump(data)
case let .failure(error):
dump(error)
}
}