将 responseJSON 解析为 ObjectMapper

Posted

技术标签:

【中文标题】将 responseJSON 解析为 ObjectMapper【英文标题】:Parse responseJSON to ObjectMapper 【发布时间】:2019-05-29 19:55:20 【问题描述】:

我目前正在从 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 的 Alamofire

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 = "vpozo@montran.com";
    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 = "vpozo@gmail.com";
fullName = "Victor Pozo";
id = 6;
phoneNumber = 099963212;
token = 6;
)

我想在 Object 中使用它,例如在 View Controller 中使用 user.token,可能我真的很困惑,尝试使用通用属性进行映射。

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

【问题讨论】:

嗨 Victor... 请查看 SwiftyJSON 库以了解 swift。它可以帮助您直接将 JSON 响应作为对象获取。这是链接 => github.com/SwiftyJSON/SwiftyJSON 嗨@CedanMisquith,我一直在尝试一些在cocoapods 中的依赖项,安装了Swifty,但我不知道如何使用数据键和值,然后将其解析为对象。我会再试一次谢谢。 我绝对可以帮助您编写代码。这很简单,我将以您的 JSON 为例并发布答案。 【参考方案1】:

首先,您需要一个使用 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 = headers 现在可以使用了吗? .allHTTPHEaderFields 还有一个问题,所以我在我的视图控制器上使用了一个点击按钮,然后它调用了一个像 makeNetworkRequest 这样的函数,我应该如何调用一个新的控制器并使用该数据,在 Android 中我使用一个包,但是我可以如何使用swift中新视图中的数据,非常感谢您的帮助 所以我认为标题错误正在发生,因为您获得了最新版本的 Alamofire 库并且语法已更改。所以我认为改变语法是你做的正确的事情。现在告诉我我是否正确......您想在服务器请求成功响应后移动到新的视图控制器,然后您想在新的视图控制器中使用该响应吗??? 好吧,你现在卡在哪里了吗??您是否能够访问新视图控制器中的数据?? SwiftyJSON 完成了一切,我能够使用带有构造函数 init(userView:JSON) self.fullName = userView["fullName"].stringValue 的结构将其解析为对象,然后使用 completion:@escaping(JSON) -&gt; Void 将其解析为对象,然后在 viewController let user=UserObject(userObject:userJson) 中解析它。您的问题的答案是肯定的,我想显示用户信息以及如何保留令牌以在其他请求中使用它。我还需要迭代帐户才能在pickerview 上使用它let jsonAccounts = response["data"] 给了我2 个帐户。顺便说一句非常感谢您的帮助 所以要存储Token,您可以查看UserDefaults。这将帮助您以 key 名称将令牌存储在您的应用中,您可以使用该 key 在您的应用中的任何位置检索它。

以上是关于将 responseJSON 解析为 ObjectMapper的主要内容,如果未能解决你的问题,请参考以下文章

将 alamofire 响应解析为 JSON 返回 nil

Gradle 3.4.1 无法使用 Proguard 将响应解析为 Object

responseJSON 没有响应

SwiftyJSON Alamofire 无法使用类型为 ((_,_,_,_))->_) 的参数列表调用 responseJSON

将JSON转换为Java Object,如何使用Jackson解析BadgerFish约定

在 Alamofire responseJSON 理解中返回 Void 的结构体