Сопоставление объекта JSON с классом/структурой Swift

Мне нужно "реплицировать" entiry, который возвращается из службы удаленного веб-API в JSON. Это выглядит так:

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

Здесь моя попытка:

struct Entity1 {
 struct Details1 {
 let field1: ******
 let field2: String
 let data: [String: String]
 }
 struct Details2 {
 let field1: ******
 let field2: String
 }
 let field1: String
 static let entityName = "Entity1"
 let field2: String
 let details1: [Details1]
 let details2: Details2 
}
  • Это хорошая идея использовать структуры вместо классов для такой цели Как мой?
  • Можно ли каким-либо образом определить вложенную структуру или класс, скажем, Details1 и создать переменную в одно и то же время?

Вот так:

//doesn't compile 
struct Entity1 {
 let details1: [Details1 { 
 let field1: ******
 let field2: String
 let data: [String: String]
}]
5 ответов

Вы можете использовать любые, если доступны следующие хорошие библиотеки с открытым исходным кодом для обработки сопоставления JSON с объектом в Swift, посмотрите:

У каждого есть хороший хороший учебник для начинающих.

Что касается темы struct или class, вы можете рассмотреть следующий текст из The Swift Programming Language:

Строковые экземпляры всегда передаются по значению, а класс экземпляры всегда передаются по ссылке. Это означает, что они подходит для различных задач. Поскольку вы считаете данные конструкции и функциональные возможности, необходимые для проекта, должна ли каждая конструкция данных быть определена как класс или как структура.

В качестве общего руководства рассмотрите вопрос о создании структуры, когда один или несколько из этих условий:

  • Основной целью структур является инкапсуляция нескольких относительно простых значений данных.
  • Разумно ожидать, что инкапсулированные значения будут скопированы, а не будут указаны, когда вы назначаете или передаете экземпляр этой структуры.
  • Любые свойства, хранящиеся в структуре, сами являются типами значений, которые также следует скопировать, а не ссылаться.
  • Структуре не нужно наследовать свойства или поведение другого существующего типа.

Примеры хороших кандидатов для структур включают:

  • Размер геометрической формы, возможно, инкапсулирует свойство width и свойство height, оба типа ******.
  • Способ ссылаться на диапазоны внутри серии, возможно, инкапсулируя свойство start и свойство length, как типа Int.
  • Точка в трехмерной системе координат, возможно, инкапсулирующая свойства x, y и z, каждый из которых является двойным.

Во всех остальных случаях определите класс и создайте экземпляры этого класса для управления и передачи по ссылке. На практике это означает, что большинство пользовательских конструктов данных должны быть классами, а не структурами.

Надеюсь, это поможет вам.


HandyJSON - именно то, что вам нужно. См. Пример кода:

struct Animal: HandyJSON {
 var name: String?
 var id: String?
 var num: Int?
}
let jsonString = "{\"name\":\"cat\",\"id\":\"12345\",\"num\":180}"
if let animal = JSONDeserializer.deserializeFrom(json: jsonString) {
 print(animal)
}

https://github.com/alibaba/handyjson


Отображение JSON в Swift

Подробнее

  • xCode 9.1, swift 4
  • xCode 8.2.1, swift 3

Задача:

Получить результаты поиска itunes с помощью iTunes Search API с простым запросом https://itunes.apple.com/search?term=jack+johnson

Требование:

Podfile

platform :ios, '8.0'
use_frameworks!
target 'stackoverflow-29749652' do
pod 'Alamofire'
pod 'ObjectMapper'
end

код

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

class ItunceItem (отображение)

import Foundation
import ObjectMapper
class ItunceItem: Mappable {
 var wrapperType: String?
 var artistId:Int?
 var trackName:String?
 var trackPrice: ******?
 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)
 }
 }
 }
}

Результат

Удобный (механический) анализ json файла

http://json.parser.online.fr


Взгляните на эту удивительную библиотеку, которая идеально подходит вам, Argo on GitHub.

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


вы можете использовать SwiftyJson и let json = JSONValue(dataFromNetworking) if let userName = json[0]["user"]["name"].string{ //Now you got your value }

licensed under cc by-sa 3.0 with attribution.