对于IOS网络操作-使用Alamofire和ObjectMapper处理JSON转对象感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍iosjson转model的原理,并为您提供关于Alamof
对于IOS网络操作-使用Alamofire和ObjectMapper处理JSON转对象感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍ios json转model的原理,并为您提供关于Alamofire - 优雅的处理 Swift 中的网络操作、Alamofire 、ObjectMapper 封装、AlamofireJsonToObjects、AlamofireJsonToObjects+EVReflection:一步解决JSON解析的有用信息。
本文目录一览:- IOS网络操作-使用Alamofire和ObjectMapper处理JSON转对象(ios json转model的原理)
- Alamofire - 优雅的处理 Swift 中的网络操作
- Alamofire 、ObjectMapper 封装
- AlamofireJsonToObjects
- AlamofireJsonToObjects+EVReflection:一步解决JSON解析
IOS网络操作-使用Alamofire和ObjectMapper处理JSON转对象(ios json转model的原理)
Alamofire是一个使用Swift语言写的一个网络库,操作很简单,结合ObjectMapper、AlamofireObjectMapper,可以轻松的将JSON数据转换为对象类型!
Alamofire:https://github.com/Alamofire/Alamofire
ObjectMapper:https://github.com/Hearst-DD/ObjectMapper
ALamoObjectmapper:https://github.com/tristanhimmelman/AlamofireObjectMapper
假设有个地址返回如下JSON数据:
{
"meta": {
"total": "16868",
"time": "0.435",
"limit": "10",
"offset": 0,
"currency": "CNY",
"symbol": "¥"
},
"products": [
{
"time_updated": "1432808931",
"commission": "363.42",
"price": "6,056.92",
"sku": "517569",
"upc": "",
"pweight": null,
"product_id": "82808bcd27eeb65dd15740aee40ec07c",
"product_image": "http://images.rewardstyle.com/img?v=1.3&p=82808bcd27eeb65dd15740aee40ec07c",
"product_type": "1",
"product_name": "Cape-back crepe and chiffon mini dress",
"advertiser": "NET-A-PORTER UK",
"designer": "Gareth Pugh",
"category": "WOMEN->Clothing->Dresses"
},
{
"time_updated": "1432808931",
"commission": "1,359.23",
"price": "22,653.85",
"sku": "549499",
"upc": "",
"pweight": null,
"product_id": "e147fbbf30c65538b367f3a6ab539252",
"product_image": "http://images.rewardstyle.com/img?v=1.3&p=e147fbbf30c65538b367f3a6ab539252",
"product_type": "1",
"product_name": "Woven suede tote",
"advertiser": "NET-A-PORTER UK",
"designer": "Loewe",
"category": "WOMEN->Bags->Tote"
}]
}
使用对象的概念来解读这段JSON数据,它包含Meta和Product:Meta是一个对象,Products是一个数组类型,包含了多个Product对象。
我们首先使用ObjectMapper库定义的规则,来写一个实体类。
class Meta : Mappable{
var total:String?
var time:Double?
var limit:String?
var offset:String?
var currency:String?
var symbol:String?
init(){}
required init?(_ map: Map){
mapping(map)
}
func mapping(map: Map) {
total <- map["total"]
time <- map["time"]
limit <- map["limit"]
offset <- map["offset"]
currency <- map["currency"]
symbol <- map["symbol"]
}
}
class Product : Mappable{
var time_updated:String?
var commission:String?
var price:String?
var sku:String?
var product_id:String?
var product_image:String?
var product_name:String?
var advertiser:String?
var designer:String?
var category:String?
init(){}
required init?(_ map: Map) {
mapping(map)
}
func mapping(map: Map) {
time_updated <- map["prtime_updated"]
commission <- map["age"]
price <- map["price"]
sku <- map["sku"]
product_id <- map["product_id"]
product_image <- map["product_image"]
product_name <- map["product_name"]
advertiser <- map["advertiser"]
designer <- map["designer"]
category <- map["category"]
}
}
每个实体类都实现了Mappable协议。这仅仅是JSON数据中的两个对象,现在我们要再声明下整个JSON数据的对象定义,它将作为顶层包含着Meta类和Product类:
class ProductResponse:Mappable{
var meta:Meta?
var products:[Product]?
init(){}
required init?(_ map: Map) {
mapping(map)
}
func mapping(map: Map) {
meta <- map["meta"]
products <- map["products"]
}
}
接下来,就可以使用Alamofire来操作了。这时候,可以使用AlamofireObjectMapper库,它使用extension扩展了Alamofire的response方法:
Alamofire.request(Method.GET, "请求的地址", parameters: nil, encoding: ParameterEncoding.URL).responseObject { (response:ProductResponse?, error:NSError?) -> Void in
if let products = response?.products{
for p in products{
println(p.product_name)
}
}
}// end request
json到对象类,变的非常的简单~~
tips:
本文由wp2osc导入,原文链接:http://devonios.com/ios-network-alamofire.html
由于OSChina的OpenAPI在处理content参数时会自动过滤img标签,所以无法显示图片,详见。
Alamofire - 优雅的处理 Swift 中的网络操作
总结
以上是小编为你收集整理的Alamofire - 优雅的处理 Swift 中的网络操作全部内容。
如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。
Alamofire 、ObjectMapper 封装
[可以在 debug 模式下,可以选择测试 url]
AlamafireMenager
Alamofire 、ObjectMapper 封装
demo 点这里
简介:
- 实现统一设置:超时时长、header、对 code 码的处理。。
- 统一对 url 进行了转码。(空格等特殊字符不崩溃)
- 使用简单,自动转化成为对象。(array,object,json)
- 对请求结果的清晰打印。(分为正确、错误,只有在 debug 模式会打印,可以在 AlamafireMenager_Configuration 中配置是否打印)
结构:
- AlamafireMenager_Configuration.swift
对一些公共信息的配置
- AlamofireMenager.swift
对外暴露请求的接口
- AlamofireSession.swift
对SessionManager的封装
- RequestMenager.swift
生成了request,(分为loadDataRequest与updataReqeust)
KRURLMenager对url的处理
- RespnseCodeMenager.swift
打印了请求出的信息。(成功,失败),可以继承自这个类自定义处理code
封装思路
全局的配置
///一些统一的配置
import UIKit
///域名 配置
let baseURL = "http://api.dianping.com/"
//MARK: - code 的处理
///code 处理 是否打印Log日志
let isPrintSucceedNetWorkLog: Bool = true
///是否打印失败请求
let isPrintErrorNetWorkLog: Bool = true
///是否打印请求成功后的数据
let isPrintSucceedData: Bool = isDebug
///code处理的类 更改这里 全局配置code 的处理类
let k_codeMenager: RespnseCodeMenager.Type = KRCodeHandler.self
//MARK: - 超时时间
///超时时间
let Alamafire_TimeoutIntervalForRequest:TimeInterval = 10
//MARK: - 所有请求都会带的东西比如 版本和 cookie
var Alamofire_header: [String:String]? {
get {
return [
"Version": KR_Version
]
}
}
private var versionPrivate: String?
var KR_Version: String {
get {
if let versionPrivate_ = versionPrivate {
return versionPrivate_
}
versionPrivate = (Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String)
return versionPrivate ?? "没有version"
}
}
/**
* log 在release 版本不打印
* 注意要在 项目的 budSeting中 查找 `Other Swift Flags`,修改debug模式的flag 为“DEBUG”
*/
func dPrint(_ item: @autoclosure () -> Any) {
if isDebug {
print(item())
}
}
///是否为debug模式
var isDebug: Bool {
get {
#if DEBUG
return true
#else
return false
#endif
}
}
1. 对 url 的封装
KRURLMenager
: 对 url 的 path 进行了一个特殊字符的处理,并返回一个不可选类型的 URL
class KRURLMenager: NSObject {
static let baseURLString = baseURL
private class func getBaseURLStr(_ str: String) -> (String) {
return KRURLMenager.baseURLString + str
}
///返回一个url 并且 cach处理
class func getURL(_ path:String) throws -> URL {
var urlStr = KRURLMenager.getBaseURLStr(path)
urlStr = urlStr.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) ?? ""
guard let URL = URL(string: urlStr) else { throw AFError.invalidURL(url: urlStr) }
return URL
}
}
2. 对 Request 的封装
RequestMenager
: 要把全局的 header 传入到 Request 中,且做了特殊字符的处理, 默认生成了全局的配置参数对象,根据传入的参数来拼接 url 参数,最后返回一个 DataRequest
/// qury 参数
private let query_Parameter = URLEncoding.init(destination: .queryString)
/// body 参数
private let httpBody_Parameter = URLEncoding.init(destination: .httpBody)
//MARK: - downLoad Request
/// 获取 下载请求
///
/// - Parameters:
/// - path: url
/// - HTTPMethod_: 请求方式
/// - parameters: 请求参数
/// - parametersType: 请求参数 拼接类型
/// - Returns: DataRequest
class func getDataRequest(Path path: String,HTTPMethod HTTPMethod_: HTTPMethod? = .get,_ parameters: [String:Any]? = nil,_ parametersType: ParamaetersType? = nil) ->(DataRequest?) {
let request = RequestMenager.getURLRequest(Path: path, HTTPMethod: HTTPMethod_, parameters, parametersType)
if let request = request {
return AlamofireSession.default.sessionMenager.request(request)
}
return nil
}
class func getURLRequest(Path path: String,HTTPMethod HTTPMethod_: HTTPMethod? = .get,_ parameters: [String:Any]? = nil,_ parametersType: ParamaetersType? = nil) -> (URLRequest?){
do{
let url = try KRURLMenager.getURL(path)
var requst = URLRequest.init(url: url)
requst.httpMethod = (HTTPMethod_ ?? .get).rawValue
///传入 一些全局header 比如
for (value,key) in Alamofire_header ?? Dictionary() {
requst.setValue(value, forHTTPHeaderField: key)
}
//传入版本 "Version": "2.1.0"
switch parametersType ?? .query{
case .query:
return try query_Parameter.encode(requst, with: parameters)
case .body:
return try httpBody_Parameter.encode(requst, with: parameters)
}
} catch {
dPrint("\n 数据下载 request 转化失败 " + path + "\n")
return nil
}
}
3. 对 SessionManager 的封装
AlamofireSession
:对超时时间修改
class AlamofireSession: NSObject {
static let `default`: AlamofireSession = AlamofireSession()
/// 请求数据的 Menager
var sessionMenager: SessionManager = {
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
configuration.timeoutIntervalForRequest = TimeInterval(Alamafire_TimeoutIntervalForRequest)
let sessionMenager = SessionManager.init(configuration: configuration, delegate: AlamofireSessionDelegate(), serverTrustPolicyManager: nil)
return sessionMenager
}()
}
4. 对 Mappable 的封装
AlamofireMenagerMap
遵循了 Mappable
协议 内部实现了 func mapping(map: Map)
, 用到了运行时,获取了属性名,并调用了相应的 map 方法。 从而实现了继承自 AlamofireMenagerMap
的 model,不再需要写 func mapping(map: Map)
方法
import UIKit
import ObjectMapper
class AlamofireMenagerMap: NSObject, Mappable {
///已经key对应的属性将要赋值
private var setingValueCallBack: ((_ key:String,_ value: AnyObject)->())?
///已经key对应的属性已经赋值
private var setedValueCallBack: ((_ key:String,_ value: AnyObject)->())?
///已经key对应的属性将要赋值
func setingValue(_ callBack: @escaping (_ key:String,_ value: AnyObject)->()?){
setingValueCallBack = callBack as? ((String, AnyObject) -> ())
}
///已经key对应的属性已经赋值
func setedValue(_ callBack: @escaping (_ key:String,_ value: AnyObject)->()?){
setedValueCallBack = callBack as? ((String, AnyObject) -> ())
}
required init?(map: Map) {
}
func mapping(map: Map) {
let propertyNames = self.getPropertyNames()
for key in propertyNames {
print(key)
var property = value(forKey: key)
property <- map[key]
setingValueCallBack?(key,property as AnyObject)
setValue(property, forKey: key)
setedValueCallBack?(key,property as AnyObject)
}
}
}
5. 动态获取对象的 propertyNames
AlamofireGetProperty.swift
extension NSObject {
func getPropertyNames() -> ([String]){
var outCount:UInt32
outCount = 0
let propers = class_copyPropertyList(self.classForCoder, &outCount)!
let count:Int = Int(outCount);
print("共有\(outCount)个")
var propertyArray = [String]()
for i in 0...(count-1) {
let aPro: objc_property_t = propers[i]!
let proName:String! = String.init(utf8String: property_getName(aPro))
propertyArray.append(proName)
}
return propertyArray
}
}
使用
RespnseCodeMenager.swift
import UIKit
import Alamofire
import AlamofireObjectMapper
import ObjectMapper
public class RespnseCodeMenager: NSObject {
///继承这个这个类,并且 重写这个函数 来处理 code
class func custom_handCodeFunc(_ code: NSInteger, _ netData: Any?, _ error: Error?, _ url: URL?) {}
///继承这个这个类,并且 重写这个函数 来处理 成功code
class func custom_handSucceedCodeFunc(_ netData: Any?, _ url: URL?) {}
///继承这个这个类,并且 重写这个函数 来处理 失败code
class func custom_handDefeatCodeFunc(_ code: NSInteger,_ error: Error?, _ url: URL?) {}
///code log 处理
class func handleCode (_ code: NSInteger, _ netData: Any?, _ error: Error?, _ url: URL?) -> (Bool) {
custom_handCodeFunc(code, netData, error, url)
if code / 100 == 2 {
succeed(netData,url)
custom_handSucceedCodeFunc(netData, url)
return true
}
custom_handDefeatCodeFunc(code, error, url)
defeat(code, error, url)
return false
}
}
/// log输出
private extension RespnseCodeMenager {
class func succeed(_ netData: Any?, _ url: URL?) {
if !isPrintSucceedNetWorkLog {
return
}
let urlTemp: Any = url ?? "url 未知"
let dataTemp: Any = netData ?? "data 未知"
dPrint("\n\n✅✅✅请求成功\n✅\(urlTemp)\n")
if let dataArray = (dataTemp as? Array<Any>) {
dPrint("\netData(Array):--")
for data in dataArray {
dPrint(data)
}
}else{
dPrint("\netData(Object):--")
dPrint(dataTemp)
}
dPrint("✅✅✅\n\n\n\n")
}
class func defeat(_ code: NSInteger,_ error: Error?, _ url: URL?) {
if !isPrintErrorNetWorkLog {
return
}
let urlTemp: Any = url ?? "url 未知"
let errorTemp: Any = error ?? "error 未知"
dPrint("\n\n请求失败\n\(code)\(urlTemp)\n")
dPrint("\nerror:--")
dPrint(errorTemp)
dPrint("\n\n\n\n")
}
}
AlamofireMenager.swift
使用注意请求类型的区分,方法名称一致
- 根据 success 回调传入的 <T> 的类型返回对应的值
- T 为 [BaseMappable],则返回数组,
- T 为 BaseMappable,则返回对象,
- T 为 Any,则返回 Json 字符串。
object
//MARK: - 下载数据 相关接口
/// alamofire 数据请求 (数据为object)
///注意循环引用
/// - Parameters:
/// - path: url path
/// - method: 请求方式
/// - parameters: 参数
/// - parametersType: 参数为 query 还是 body
/// - responseDateType: 网络数据类型
/// - success: 成功的回调
/// - failure: 失败的回调
/// - Returns: Request
@discardableResult
func loadData<T:BaseMappable>(Path path: String, HTTPMethod method: RequestMethod? = .get,_ parameters: [String:Any]? = nil,_ parametersType: ParamaetersType? = nil,_ setRequest: ((_ request: DataRequest) -> Void)? = nil,Success success: @escaping (_ M:T,_ response:DataResponse<T>) -> Void, Failure failure:@escaping(_ errorMsg:String) -> Void) -> (DataRequest?) {
return self.loadDataObject(Path: path, HTTPMethod: method, parameters, parametersType, setRequest, Success: success, Failure: failure)
}
Json
/// alamofire 数据请求 (数据Json)
///注意循环引用
/// - Parameters:
/// - path: url path
/// - method: 请求方式
/// - parameters: 参数
/// - parametersType: 参数为 query 还是 body
/// - responseDateType: 网络数据类型
/// - success: 成功的回调
/// - failure: 失败的回调
/// - Returns: Request
@discardableResult
func loadData(Path path: String, HTTPMethod method: RequestMethod? = .get,_ parameters: [String:Any]? = nil,_ parametersType: ParamaetersType? = nil,_ setRequest: ((_ request: DataRequest) -> Void)? = nil,Success success: @escaping (_ json: Any,_ response: DataResponse<Any>) -> Void, Failure failure:@escaping(_ errorMsg:String) -> Void) -> (DataRequest?) {
return self.loadDataJson(Path: path, HTTPMethod: method, parameters, parametersType, setRequest, Success: success, Failure: failure)
}
array
/// alamofire 数据请求 (数据数组)
///注意循环引用
/// - Parameters:
/// - path: url path
/// - method: 请求方式
/// - pxarameters: 参数
/// - parametersType: 参数为 query 还是 body
/// - responseDateType: 网络数据类型
/// - success: 成功的回调
/// - failure: 失败的回调
/// - Returns: Request
@discardableResult
func loadData<T:BaseMappable>(Path path: String, HTTPMethod method: RequestMethod? = .get,_ parameters: [String:Any]? = nil,_ parametersType: ParamaetersType? = nil,_ setRequest: ((_ request: DataRequest) -> Void)? = nil,Success success: @escaping ([T],_ response: DataResponse<[T]>) -> Void, Failure failure:@escaping(_ errorMsg:String) -> Void) -> (DataRequest?) {
return self.loadDataArray(Path: path, HTTPMethod: method, parameters, parametersType, setRequest, Success: success, Failure: failure)
}
上传
///上传
///
/// - Parameters:
/// - urlStr: url
/// - method: 请求方法
/// - params: 请求参数(根据key来拼接(后续可能回接入用户名与token))
/// - data: 照片数据
/// - name: 需要与后台协商成统一字段
/// - fileNameArray: 文件名称,看后台有没有要求
/// - headers: header 可以没有
/// - mimeType: mimeType
/// - success: 成功
/// - failture: 失败 -- 如果没有数据,相当于失败。
func upload(_ urlStr : String,_ method: HTTPMethod, _ params:[String:String],_ data: [Data],_ names:[String],_ fileNames:[String], _ headers: [String:String]?,_ mimeType: String, success : @escaping (_ response : [String : AnyObject])->(), failture : @escaping (_ error : Error)->()) {
self.uploadFunc(urlStr, method, params, data, names, fileNames, headers, mimeType, success: success, failture: failture)
}
上传图片
///图片 上传
///
/// - Parameters:
/// - urlStr: url
/// - method: 请求方法
/// - params: 请求参数(根据key来拼接(后续可能回接入用户名与token))
/// - data: 照片数据
/// - name: 需要与后台协商成统一字段
/// - fileNameArray: 文件名称,看后台有没有要求
/// - headers: header 可以没有
/// - mimeType: mimeType
/// - success: 成功
/// - failture: 失败 -- 如果没有数据,相当于失败。
func uploadImage(_ urlStr : String,_ method: HTTPMethod, _ params:[String:String],_ images: [UIImage],_ names:String,_ fileNames:[String], _ headers: [String:String]?,_ compressionQuality: CGFloat? = 0.1 , _ mimeType: String ,success : @escaping (_ response : [String : AnyObject])->(), failture : @escaping (_ error : Error)->()) {
self.uploadImageFunc(urlStr, method, params, images, names, fileNames, headers, compressionQuality, mimeType, success: success, failture: failture)
}
图片:
测试必备搭配组件
可以在 debug 模式下,可以选择测试 url
demo 点这里
AlamofireJsonToObjects
AlamofireJsonToObjects 介绍
AlamofireJsonToObjects 是 一个Alamofire 扩展,它可以把 JSON 响应数据转换成使用 EVReflection 的
Swift 对象。
示例:
class WeatherResponse: EVObject { var location: String? var three_day_forecast: [Forecast] = [Forecast]() } class Forecast: EVObject { var day: String? var temperature: NSNumber? var conditions: String? } class AlamofireJsonToObjectsTests: XCTestCase { func testResponSEObject() { let URL = "https://raw.githubusercontent.com/evermeer/AlamofireJsonToObjects/master/AlamofireJsonToObjectsTests/sample_json" Alamofire.request(.GET, URL, parameters: nil) .responSEObject { (response: WeatherResponse?, error: NSError?) in // That was all... You Now have a WeatherResponse object with data } waitForExpectationsWithTimeout(10, handler: { (error: NSError!) -> Void in XCTAssertNil(error, "\(error)") }) } }
AlamofireJsonToObjects 官网
https://github.com/evermeer/AlamofireJsonToObjects
AlamofireJsonToObjects+EVReflection:一步解决JSON解析
上一篇文章中我们介绍了使用EVReflection解析JSON的方法,但是还是用到了SwiftyJSON这样的工具,那么有木有什么办法能够更简单的解决这样的问题EVReflection的作者还为我们提供了AlamofireJsonToObjects这样一个工具,让我们能够更加容易的处理JSON数据
AlamofireJsonToObjects 基于目前使用最广泛的Swift HTTP库Alamofire和我们上次提到的
EVReflection
第三方库导入
我们通过CocoaPods导入
use_frameworks!
pod "AlamofireJsonToObjects"
在用到到Swift文件中import AlamofireJsonToObjects
Demo
作为EVReflection的一个配套工具,它的使用非常简单,我们通过一个Demo一起来学习一下
构建数据模型
根据我们上次写出的数据模型,我们写出整个response的数据模型
import Foundation
import EVReflection
class CityModel:EVObject{
var city_name = ""
var city_pinyin = ""
var short_name = ""
var short_pinyin = ""
var city_id = 100010000
}
如下
class CityModelApiResponse:EVObject{
var cities = [CityModel]()
var errno = 0;
var msg = "";
}
发起网络请求
在我们的文件中import AlamofireJsonToObjects
我们这次先对Alamofire的网络请求做一些封装,我们这里使用了泛型以保证通用性
这里不再responseJSON
而是responseObject
class func invokeObject< T: EVObject >(
url:String,
parameters:[String: AnyObject]? = nil,
complete:(object: T?, error: NSError?) -> Void){
Alamofire.request(.GET, ServiceEndpointBase, parameters: nil, encoding: .URL, headers: ["apikey":"ownAPIKey"]).validate(statusCode: 200..<300).responseObject { (URLRequest:NSURLRequest?, HTTPURLResponse:NSHTTPURLResponse?, result:Result< T, NSError>) in
complete(object: result.value, error: result.error)
}
}
接下来我们写具体的涉及业务的请求方法
class func getCityListObject(complete:(object: CityModelApiResponse?, error: NSError?) -> Void){
invokeObject(ServiceEndpointBase,parameters: nil,complete: complete)
}
调用方法及结果
我们在viewDidLoad
方法中调用一下我们的网络请求方法
ServiceProxy.getCityListObject { (object, error) in
print(object!)
}
控制台结果如下
CityModelApiResponse {
hash = 5326178534503437261
key = cities, value = (
{
"city_id" = 100010000;
"city_name" = "\U5317\U4eac\U5e02";
"city_pinyin" = beijing;
"short_name" = "\U5317\U4eac";
"short_pinyin" = bj;
},
{
"city_id" = 500010000;
"city_name" = "\U5929\U6d25\U5e02";
"city_pinyin" = tianjin;
"short_name" = "\U5929\U6d25";
"short_pinyin" = tj;
},
{
"city_id" = 1800010000;
"city_name" = "\U77f3\U5bb6\U5e84\U5e02";
"city_pinyin" = shijiazhuang;
"short_name" = "\U77f3\U5bb6\U5e84";
"short_pinyin" = sjz;
},
{
"city_id" = 1800020000;
"city_name" = "\U5510\U5c71\U5e02";
"city_pinyin" = tangshan;
"short_name" = "\U5510\U5c71";
"short_pinyin" = ts;
}
...
)
key = errno, value = 0
key = msg, value = success
}
AlamofireJsonToObjects不仅提供了
responseObject
还有responseArray
,可以直接导出数组
关于IOS网络操作-使用Alamofire和ObjectMapper处理JSON转对象和ios json转model的原理的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于Alamofire - 优雅的处理 Swift 中的网络操作、Alamofire 、ObjectMapper 封装、AlamofireJsonToObjects、AlamofireJsonToObjects+EVReflection:一步解决JSON解析等相关知识的信息别忘了在本站进行查找喔。
本文标签: