Разобрать responseJSON в ObjectMapper

В настоящее время я выполняю миграцию с Android на iOS, лучше сказать с Java на Swift, я получил общий ответ в JSON, но я не могу использовать его как объект и показать его в раскадровке. Я действительно новичок в Swift, поэтому некоторое время застрял.

Я пробовал ObjectMapper, а также декодировать JSON безрезультатно.

Я объявил этот ответ, как я использовал в Java (Android)

class ResponseObjectMapper<T,R>: Mappable where T: Mappable,R:Mappable{

var data:T?
var message:String!
var error:R?

required init?(_ map: Map) {
    self.mapping(map: map)
}

func mapping(map: Map) {
    data          <- map["data"]
    message          <- map["message"]
    error          <- map["error"]
}
}

class UserMapper :Mappable{
var email:String?
var fullName:String?
var id:CLong?
var phoneNumber:String?
var token:CLong?

required init?(_ map: Map) {
}

func mapping(map: Map) {
    email <- map["email"]
    fullName <- map["fullName"]
    id <- map["id"]
    phoneNumber <- map["phoneNumber"]
    token <- map["token"]
    phoneNumber <- map["phoneNumber"]
}
}    

В моем проекте Android я использую зависимость Gson, и я смог использовать свой JSON в качестве объекта.

class ErrorMapper:Mappable{

var message:String?
var code:Int?

required init?(_ map: Map) {
}

func mapping(map: Map) {
    message          <- map["message"]
    code          <- map["code"]
}

}

Это Аламофайр, который дал мне JSON.

func login(params: [String:Any]){Alamofire.request
("http://192.168.0.192:8081/SpringBoot/user/login", method: .post, 
parameters: params,encoding: JSONEncoding.default, headers: 
headers).responseJSON {
            response in
            switch response.result {
            case .success:

                let response = Mapper<ResponseObjectMapper<UserMapper,ErrorMapper>>.map(JSONString: response.data)


                break
            case .failure(let error):

                print(error)
            }
        }
}

Если я напечатаю ответ с помощью print(response), я получу

SUCCESS: {
data =     {
    email = "[email protected]";
    fullName = "Victor Pozo";
    id = 6;
    phoneNumber = 099963212;
    token = 6;
};
error = "<null>";
message = SUCCESS;
}

и если я использую этот код, я могу получить результат с ключом и значением, но я не знаю, как использовать его как объект

if let result = response.result.value {
                    let responseDict = result as! [String : Any]
                    print(responseDict["data"])
                }

приставка:

Optional({
email = "[email protected]";
fullName = "Victor Pozo";
id = 6;
phoneNumber = 099963212;
token = 6;
})

Я хотел бы использовать его в объекте, например user.token в контроллере представления, возможно, я действительно запутался, пытаясь сопоставить общие атрибуты.

Type 'ResponseObjectMapper<UserMapper, ErrorMapper>' does not conform to protocol 'BaseMappable'

Привет, Виктор... Проверьте библиотеку SwiftyJSON для Swift. Это поможет вам получить ответ JSON напрямую как объект. Вот ссылка => github.com/SwiftyJSON/SwiftyJSON

Cedan Misquith 30.05.2019 07:23

Привет @CedanMisquith, я пробовал некоторые зависимости в Cocopods, установил Swifty, но я не понимаю, как использовать ключ данных и значение, а затем анализировать его как объект. попробую еще раз спасибо.

Victor Pozo 30.05.2019 16:19

Я определенно могу помочь вам с кодом. Это довольно просто, например, я использую ваш JSON и опубликую ответ.

Cedan Misquith 30.05.2019 16:26
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
779
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Прежде всего вам понадобится Network Manager, который использует Alamofire для выполнения всех ваших запросов. Я сделал обобщенный, который выглядит примерно так. Вы можете изменить его по своему усмотрению.

import Foundation
import Alamofire
import SwiftyJSON

class NetworkHandler: NSObject {

let publicURLHeaders : HTTPHeaders = [
    "Content-type" : "application/json"
]

let privateURLHeaders : HTTPHeaders = [
    "Content-type" : "application/json",
    "Authorization" : ""
]

enum RequestType {
    case publicURL
    case privateURL
}

func createNetworkRequestWithJSON(urlString : String , prametres : [String : Any], type : RequestType, completion:@escaping(JSON) -> Void) {

    let internetIsReachable = NetworkReachabilityManager()?.isReachable ?? false
    if !internetIsReachable {
        AlertViewManager.sharedInstance.showAlertFromWindow(title: "", message: "No internet connectivity.")
    } else {
        switch type {
        case .publicURL :
            commonRequest(urlString: baseURL+urlString, parameters: prametres, completion: completion, headers: publicURLHeaders)
            break
        case .privateURL:
            commonRequest(urlString: baseURL+urlString, parameters: prametres, completion: completion, headers: privateURLHeaders)
            break
        }
    }
}

func commonRequest(urlString : String, parameters : [String : Any], completion : @escaping (JSON) -> Void , headers : HTTPHeaders){

    print("urlString:"+urlString)
    print("headers:")
    print(headers)
    print("parameters:")
    print(parameters)

    let url = NSURL(string: urlString)
    var request = URLRequest(url: url! as URL)
    request.httpMethod = "POST"
    request.httpHeaders = headers
    request.timeoutInterval = 10
    let data = try! JSONSerialization.data(withJSONObject: parameters, options: JSONSerialization.WritingOptions.prettyPrinted)

    let json = NSString(data: data, encoding: String.Encoding.utf8.rawValue)
    if let json = json {
        print("parameters:")
        print(json)
    }

    request.httpBody = json!.data(using: String.Encoding.utf8.rawValue)
    let alamoRequest = AF.request(request as URLRequestConvertible)
    alamoRequest.validate(statusCode: 200..<300)
    alamoRequest.responseJSON{ response in
        print(response.response?.statusCode as Any )
        if let status = response.response?.statusCode {
            switch(status){
            case 201:
                print("example success")
                SwiftLoader.hide()
            case 200 :
                if let json = response.value {
                    let jsonObject = JSON(json)
                    completion(jsonObject)
                }
            default:
                SwiftLoader.hide()
                print("error with response status: \(status)")
            }
        }else{
            let jsonObject = JSON()
            completion(jsonObject)
            SwiftLoader.hide()
        }
    }
}
}

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

func makeNetworkRequest(){
    let networkHandler = NetworkHandler()
    var parameters : [String:String] = [:]
    parameters["email"] = usernameTextField.text
    parameters["pass"] = passwordTextField.text
    networkHandler.createNetworkRequestWithJSON(urlString: "http://192.168.0.192:8081/SpringBoot/user/login", prametres: parameters, type: .publicURL, completion: self.handleResponseForRequest)
}


func handleResponseForRequest(response: JSON){
    if let message = response["message"].string{
        if message == "SUCCESS"{

            if let email = response["data"]["email"].string{
                //Do something with email.
            }

            if let fullName = response["data"]["fullName"].string{
                //Do something with fullName.
            }

            if let id = response["data"]["id"].int{
                //Do something with id.
            }

            if let phoneNumber = response["data"]["phoneNumber"].int64{
                //Do something with phoneNumber.
            }

            if let token = response["data"]["token"].int{
                //Do something with token.
            }
        }else{
            //Error
        }
    }
}

Надеюсь это поможет. Дайте мне знать, если вы застряли где-нибудь.

Я благодарен за вашу помощь @CedanMisquith, но у меня есть сомнения по поводу менеджера, я получил эту ошибку. Значение типа «URLRequest» не имеет члена «httpHeaders» по запросу. httpHeaders = заголовки, с которыми теперь он работал, все в порядке? .allHTTPHEaderFields еще один вопрос, поэтому я использую кнопку щелчка на моем контроллере представления, затем он вызывает функцию, например makeNetworkRequest, как мне вызвать новый контроллер и использовать эти данные, в Android я использую пакет, но как я могу использовать данные в новом представлении в Swift, большое спасибо за вашу помощь

Victor Pozo 30.05.2019 19:47

Поэтому я думаю, что ошибка заголовков происходит из-за того, что вы получили последнюю версию библиотеки Alamofire, и синтаксис изменился. Поэтому я думаю, что изменение синтаксиса — это правильно, что вы сделали. Теперь скажите мне, прав ли я... вы хотите перейти на новый контроллер представления после успешного ответа на запрос сервера, а затем вы хотите использовать этот ответ в новом контроллере представления правильно ???

Cedan Misquith 31.05.2019 03:38

Хорошо, так ты застрял где-нибудь сейчас ?? Удалось ли вам получить доступ к данным в вашем новом контроллере представления??

Cedan Misquith 31.05.2019 08:04

SwiftyJSON делает все, я смог проанализировать как объект, используя структуру с конструктором init(userView:JSON){ self.fullName = userView["fullName"].stringValue , и проанализировать его как объект, используя completion:@escaping(JSON) -> Void, а затем в viewController let user=UserObject(userObject:userJson). Ответ на ваш вопрос: да, я хочу показать информацию о пользователе и как сохранить токен, чтобы использовать его в другом запросе. Также мне нужно повторять учетные записи, чтобы использовать его в режиме выбора let jsonAccounts = response["data"] дает мне 2 учетные записи. Кстати Спасибо большое за вашу помощь

Victor Pozo 31.05.2019 08:22

Итак, для хранения Token вы можете заглянуть в UserDefaults. Это поможет вам сохранить токен в вашем приложении под именем key, и вы сможете получить его в любом месте вашего приложения, используя это имя key.

Cedan Misquith 31.05.2019 08:27

Другие вопросы по теме