Можем ли мы использовать struct на Swift?Или есть другой способ? - PullRequest
0 голосов
/ 31 мая 2018

Итак, у меня есть пользовательская структура JSON, которая выглядит следующим образом:

- results: {
    meta: {}
    users: []
  },
- status:

Я хочу получить пользователя, поэтому модель User, которую я реализую для получения JSON, выглядит следующим образом:

struct Response: Decodable {

    let results: Result
    let status: Int
}

struct Result: Decodable {

    let meta: Meta
    let users: [User]
}

struct Meta: Decodable {

    let total_data: Int
    let total_page: Int
}

struct User: Decodable {

    let avatar_url: String
    let created_at: String
    let updated_at: String
    let email: String
    let id: Int
    let name: String
    let username: String
}

Это работает, но когда у меня есть другой JSON, структура которого похожа, скажем так:

- results: {
        meta: {}
        rooms: []
      },
    - status:

И когда я создаю Room модель с другой struct Response на ней, это приведет к ошибке, потому что это дублированное объявление.

Можно ли повторно использовать struct в Swift?Или есть какой-нибудь удобный способ сделать это?

Спасибо

Ответы [ 4 ]

0 голосов
/ 31 мая 2018

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

Начните с ваших моделей данных

struct User: Decodable {
    let avatar_url: String
    let created_at: String
    let updated_at: String
    let email: String
    let id: Int
    let name: String
    let username: String
}

struct Room: Decodable {
    let id: Int
    let name: String
}

Цель состоит в том, чтобы получить красивые составные типы.

typealias UserResponse = Response<Result<User, Meta>>
typealias RoomResponse = Response<Result<Room, Meta>>

Обобщенные типы для построения из

struct Response<ResultType: Decodable>: Decodable {
    let results: ResultType
    let status: Int
}

struct Result<ItemType: Decodable, MetaType: Decodable>: Decodable {
    let meta: MetaType
    let items: [ItemType]
}

Четный Meta является отдельной частью композиции.

struct Meta: Decodable {
    let total_data: Int
    let total_page: Int
}

Теперь давайте скажем, что нам нужен пользовательский Meta для ответа Room

struct PagedMeta: Decodable {
    let current_page: Int
    let page_count: Int
}

Вот новый тип

typealias RoomPagedResponse = Response<Result<Room, PagedMeta>>
0 голосов
/ 31 мая 2018

Вы можете попробовать использовать дженерики следующим образом:

struct Response<ResultType> : Decodable where ResultType : Decodable {
    let results: ResultType
    let status: Int
}

, а затем использовать эту структуру через:

struct Result: Decodable {
    let something: String
}

let decoder = JSONDecoder()
let data = "{\"status\":123,\"results\":{\"something\":\"hi\"}}".data(using: .utf8)!
let value = try! decoder.decode(Response<Result>.self, from: data) // will be of type Response<Result>
0 голосов
/ 31 мая 2018

У вас есть один вариант - повторно использовать Meta и Status Если вы используете sm

Для пользователя Вы можете заменить имя

struct UserResult: Decodable {

    let meta: Meta
    let users: [User]
}

struct UserResponse: Decodable {

    let results: UserResult
    let status: Int
}

и для комнаты

struct RoomResult: Decodable {

    let meta: Meta
    let users: [Room]
}

struct RoomResponse: Decodable {

    let results: RoomResult
    let status: Int
}
0 голосов
/ 31 мая 2018

Вы можете использовать дженерики.

struct Response<T: Decodable>: Decodable {
    let results: Result<T>
    let status: Int
}

struct Result<T: Decodable>: Decodable {
    let meta: Meta
    let objects: [T]
}

struct Meta: Decodable {    
    let total_data: Int
    let total_page: Int
}

struct User: Decodable {
    let avatar_url: String
    let created_at: String
    let updated_at: String
    let email: String
    let id: Int
    let name: String
    let username: String
}

let userResponse: Response<User>?
...