Mapping a JSON Object to a Swift Class / Structure

I need to "replicate" entiry, which returns from the remote web API service in JSON. It looks like this:

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

Here is my attempt:

 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 } 
  • It is a good idea to use structures instead of classes for this purpose. How is mine?
  • Is there any way to define a nested structure or class, say Details1, and create a variable at the same time?

Like this:

 //doesn't compile struct Entity1 { let details1: [Details1 { let field1: UInt32 let field2: String let data: [String: String] }] 
+10
json swift
source share
6 answers

You can use any if the following good open source libraries are available to handle JSON mapping to an object in Swift, see:

Everyone has a good good primer.

Regarding the topic struct or class , you can consider the following text from The Swift Programming Language :

String instances are always passed by value, and class instances are always passed by reference. This means that they are suitable for various tasks. Since you consider the data constructs and functionality needed for the project, whether each data construct should be defined as a class or as a structure.

As a general guideline, consider creating a structure when one or more of these conditions are true:

  • The main goal of structures is to encapsulate several relatively simple data values.
  • It is reasonable to expect that the encapsulated values ​​will be copied, and not indicated, when you assign or transfer an instance of this structure.
  • Any properties stored in the structure are themselves types of values ​​that should also be copied, not referenced.
  • A structure does not need to inherit the properties or behavior of another existing type.

Examples of good candidates for structures include:

  • The size of the geometric shape may encapsulate the width property and the height property, both of Double types.
  • A way to refer to ranges within a series, possibly by encapsulating the start property and the length property, like an Int.
  • A point in a three-dimensional coordinate system, possibly encapsulating the properties of x, y and z, each of which is double.

In all other cases, define a class and create instances of this class to manage and pass by reference. In practice, this means that most custom data constructs should be classes, not structures.

Hope this helps you.

+17
source share

HandyJSON is exactly what you need. See Code Example:

 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

+5
source share

the details

  • Xcode 10.2.1 (10E1001), Swift 5

communication

Beans:

More information:

  • Coded
  • More examples of using Codable and ObjectMapper in Swift 5

task

Get itunes search results using the iTunes Search API with a simple query https://itunes.apple.com/search?term=jack+johnson

Full sample

 import UIKit import Alamofire // Itunce api doc: https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search-api/#searching class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() loadData() } private func loadData() { let urlString = "https://itunes.apple.com/search?term=jack+johnson" Alamofire.request(urlString).response { response in guard let data = response.data else { return } do { let decoder = JSONDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase let result = try decoder.decode(ItunceItems.self, from: data) print(result) } catch let error { print("\(error.localizedDescription)") } } } } struct ItunceItems: Codable { let resultCount: Int let results: [ItunceItem] } struct ItunceItem: Codable { var wrapperType: String? var artistId: Int? var trackName: String? var trackPrice: Double? var currency: String? } 
+3
source share

you can use SwiftyJson and let json = JSONValue(dataFromNetworking) if let userName = json[0]["user"]["name"].string{ //Now you got your value }

0
source share

Take a look at this amazing library that's perfect for you, Argo on GitHub .

In your case, the structure is fine. You can learn more about how to choose between structure and class here .

0
source share

You can go with this extension for Alamofire https://github.com/sua8051/AlamofireMapper

Declare a class or 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! } 

Using:

 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) } } 
0
source share

All Articles