【iOS】JSONModel的基本使用

文章目录


前言

JSONModel 是一个用于 Objective-C 的开源库,它用于简化 JSON 数据与 iOS 应用中的数据模型之间的转换。

其最主要的优点就是简化 JSON 数据解析与减少模型代码的编写,JSONModel可以将json数据直接映射到我们的对象 中,对于我们获取的数据更加方便。同时对于模型的嵌套数据的获取更加便捷。


一、导入JSONModel

这里笔者在先前的博客中已经讲的很详细,不再赘述,详见【iOS】Cocoapods的安装以及使用


二、JSONModel的基本使用

单单讲解JSONModel理论知识过于抽象,笔者将会给出例子来对JSONModel进行讲解,JSONModel请求的网络数据的API如下:API

通过上图我们可以看到我们的Json数据共有三个字段,这三个字段就可以成为我们JSONModel类中的属性

1.基本用法

我们首先创建一个继承于JSONModel的TestModel,然后将字段作为该类中的属性

objectivec 复制代码
#import "JSONModel.h"
#import "Manager.h"
NS_ASSUME_NONNULL_BEGIN

//{
//    "status":1,
//    "msg":"【更新内容】\r\n\r\n★ 多图有标记 流量壕忽略\r\n★ 出门前离线 没网也能看\r\n★ 喜欢请好评 不喜快吐槽\r\n★ 萌妹工程师 邮箱在下面\r\nmua@zhihu.com\r\n(一般人我们不告诉他)",
//    "latest":"2.5"
//}

@interface TestModel : JSONModel

@property (nonatomic, assign) int status;
@property (nonatomic, copy) NSString *msg;
@property (nonatomic, copy) NSString *latest;

@end

NS_ASSUME_NONNULL_END

然后我们在进行网络请求时将我们请求到的数据导入到我们的Model中

objectivec 复制代码
    [manager GET:url parameters:nil headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        TestModel *testModel = [[TestModel alloc] initWithDictionary:responseObject error:nil];
        NSLog(@"%@", testModel);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"Error: %@", error);
    }];

然后我们打印的到了如下数据


2.模型集合

但是如果对于我们的Json数据中有着key的嵌套,那么就会这样输出就会出现一些问题

例如此时我们请求的json数据如下:

objectivec 复制代码
{
    "date":"20231018",
    "stories":[
        {
            "image_hue":"0xb3a27d",
            "title":"长平之战,廉颇主张防守,是对是错?",
            "url":"https:\/\/daily.zhihu.com\/story\/9766453",
            "hint":"众人皆醒我独醉 · 7 分钟阅读",
            "ga_prefix":"101807",
            "images":[
                "https:\/\/picx.zhimg.com\/v2-e3db2cb91bb097c111072487caf70737.jpg?source=8673f162"
            ],
            "type":0,
            "id":9766453
        },
        {
            "image_hue":"0x6d502d",
            "title":"不用化肥,如何让没有肥力的土地快速变得有肥?",
            "url":"https:\/\/daily.zhihu.com\/story\/9766437",
            "hint":"刘文龙PhD · 5 分钟阅读",
            "ga_prefix":"101807",
            "images":[
                "https:\/\/picx.zhimg.com\/v2-709e63e4a8870b25887454f4f587234b.jpg?source=8673f162"
            ],
            "type":0,
            "id":9766437
        },
        {
            "image_hue":"0x7c5b26",
            "title":"瞎扯 · 如何正确地吐槽",
            "url":"https:\/\/daily.zhihu.com\/story\/9766461",
            "hint":"VOL.3215",
            "ga_prefix":"101806",
            "images":[
                "https:\/\/picx.zhimg.com\/v2-924083b893973c3ae7d12b9c11155d8d.jpg?source=8673f162"
            ],
            "type":0,
            "id":9766461
        }
    ],
    "top_stories":[
        {
            "image_hue":"0xb3a27d",
            "hint":"作者 \/ 众人皆醒我独醉",
            "url":"https:\/\/daily.zhihu.com\/story\/9766453",
            "image":"https:\/\/picx.zhimg.com\/v2-b3b010976682ab3b7ba240c318e3cf9b.jpg?source=8673f162",
            "title":"长平之战,廉颇主张防守,是对是错?",
            "ga_prefix":"101807",
            "type":0,
            "id":9766453
        },
        {
            "image_hue":"0xb37229",
            "hint":"作者 \/ 匿名用户",
            "url":"https:\/\/daily.zhihu.com\/story\/9766426",
            "image":"https:\/\/pic1.zhimg.com\/v2-15928648a5270b506392f48a7eee2d8c.jpg?source=8673f162",
            "title":"你曾经被哪些自己所学专业的鬼畜知识震惊过?",
            "ga_prefix":"101707",
            "type":0,
            "id":9766426
        },
        {
            "image_hue":"0x3b3045",
            "hint":"作者 \/ 单长殷",
            "url":"https:\/\/daily.zhihu.com\/story\/9766350",
            "image":"https:\/\/pic1.zhimg.com\/v2-52190997fe05a0af480a2ae26c3775a9.jpg?source=8673f162",
            "title":"小事 · 哪些时刻让你体会到「知识的实用与浪漫」?",
            "ga_prefix":"101407",
            "type":0,
            "id":9766350
        }
    ]
}

Model属性如下:

objectivec 复制代码
//声明网络请求中要接受数据的两个协议
@protocol StoriesModel
@end

@protocol Top_StoriesModel
@end

#import "JSONModel.h"

NS_ASSUME_NONNULL_BEGIN

@interface StoriesModel : JSONModel
@property (nonatomic, copy) NSString* image_hue;
@property (nonatomic, copy) NSString* title;
@property (nonatomic, copy) NSString* url;
@property (nonatomic, copy) NSString* hint;
@property (nonatomic, copy) NSString* ga_prefix;
@property (nonatomic, copy) NSString* type;
@property (nonatomic, copy) NSString* id;

@end

@interface Top_StoriesModel : JSONModel
@property (nonatomic, copy) NSString* image_hue;
@property (nonatomic, copy) NSString* hint;
@property (nonatomic, copy) NSString* url;
@property (nonatomic, copy) NSString* title;
@property (nonatomic, copy) NSString* ga_prefix;
@property (nonatomic, copy) NSString* type;
@property (nonatomic, copy) NSString* id;

@end

@interface TestModel3 : JSONModel
@property (nonatomic, copy) NSString *date;//三个同类型的
@property (nonatomic, copy) NSArray<StoriesModel>* stories;
@property (nonatomic, copy) NSArray<Top_StoriesModel>* top_stories;

@end

NS_ASSUME_NONNULL_END

注意:NSArray后的<>包含一个协议。这与OC泛型系统不同。它们不是相互排斥的,但是对于JSONModel来说,协议必须到位。

此时我们仍然直接打印我们的Model

objectivec 复制代码
    [manager GET:url parameters:nil headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        TestModel3 *testModel = [[TestModel3 alloc] initWithDictionary:responseObject error:nil];
        NSLog(@"%@", testModel);
        mainModelBolck(testModel);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"Error: %@", error);
    }];

出现如下结果:

objectivec 复制代码
<TestModel3> 
   [date]: 20231018
   [stories]: (
       "<StoriesModel> \n   [image_hue]: 0xb3a27d\n   [ga_prefix]: 101807\n   [id]: 9766453\n   [title]: \U957f\U5e73\U4e4b\U6218\Uff0c\U5ec9\U9887\U4e3b\U5f20\U9632\U5b88\Uff0c\U662f\U5bf9\U662f\U9519\Uff1f\n   [hint]: \U4f17\U4eba\U7686\U9192\U6211\U72ec\U9189 \U00b7 7 \U5206\U949f\U9605\U8bfb\n   [type]: 0\n   [url]: https://daily.zhihu.com/story/9766453\n</StoriesModel>",
       "<StoriesModel> \n   [image_hue]: 0x6d502d\n   [ga_prefix]: 101807\n   [id]: 9766437\n   [title]: \U4e0d\U7528\U5316\U80a5\Uff0c\U5982\U4f55\U8ba9\U6ca1\U6709\U80a5\U529b\U7684\U571f\U5730\U5feb\U901f\U53d8\U5f97\U6709\U80a5\Uff1f\n   [hint]: \U5218\U6587\U9f99PhD \U00b7 5 \U5206\U949f\U9605\U8bfb\n   [type]: 0\n   [url]: https://daily.zhihu.com/story/9766437\n</StoriesModel>",
       "<StoriesModel> \n   [image_hue]: 0x40312d\n   [ga_prefix]: 101807\n   [id]: 9766445\n   [title]: \U5982\U679c\U6c38\U751f\U4eba\U7c7b\U7ec6\U80de\U300c\U6d77\U62c9\U7ec6\U80de\U300d\U6cc4\U9732\U4e86\U4f1a\U6709\U5371\U9669\U5417\Uff1f\n   [hint]: \U567c\U91cc\U556a\U5566\U7830 \U00b7 1 \U5206\U949f\U9605\U8bfb\n   [type]: 0\n   [url]: https://daily.zhihu.com/story/9766445\n</StoriesModel>",
       "<StoriesModel> \n   [image_hue]: 0x6d9c95\n   [ga_prefix]: 101807\n   [id]: 9766457\n   [title]: \U5fae\U8f6f\U7b97\U6cd5\U9762\U8bd5\U9898\U300c\U5224\U65ad\U9ebb\U5c06\U662f\U5426\U548c\U724c\U300d\U5e94\U8be5\U5982\U4f55\U505a\Uff1f\n   [hint]: \U8001\U987d\U7ae5 \U00b7 22 \U5206\U949f\U9605\U8bfb\n   [type]: 0\n   [url]: https://daily.zhihu.com/story/9766457\n</StoriesModel>",
       "<StoriesModel> \n   [image_hue]: 0x7c5b26\n   [ga_prefix]: 101806\n   [id]: 9766461\n   [title]: \U778e\U626f \U00b7 \U5982\U4f55\U6b63\U786e\U5730\U5410\U69fd\n   [hint]: VOL.3215\n   [type]: 0\n   [url]: https://daily.zhihu.com/story/9766461\n</StoriesModel>"
   )
   [top_stories]: (
       "<Top_StoriesModel> \n   [image_hue]: 0xb3a27d\n   [ga_prefix]: 101807\n   [id]: 9766453\n   [title]: \U957f\U5e73\U4e4b\U6218\Uff0c\U5ec9\U9887\U4e3b\U5f20\U9632\U5b88\Uff0c\U662f\U5bf9\U662f\U9519\Uff1f\n   [hint]: \U4f5c\U8005 / \U4f17\U4eba\U7686\U9192\U6211\U72ec\U9189\n   [type]: 0\n   [url]: https://daily.zhihu.com/story/9766453\n</Top_StoriesModel>",
       "<Top_StoriesModel> \n   [image_hue]: 0xb37229\n   [ga_prefix]: 101707\n   [id]: 9766426\n   [title]: \U4f60\U66fe\U7ecf\U88ab\U54ea\U4e9b\U81ea\U5df1\U6240\U5b66\U4e13\U4e1a\U7684\U9b3c\U755c\U77e5\U8bc6\U9707\U60ca\U8fc7\Uff1f\n   [hint]: \U4f5c\U8005 / \U533f\U540d\U7528\U6237\n   [type]: 0\n   [url]: https://daily.zhihu.com/story/9766426\n</Top_StoriesModel>",
       "<Top_StoriesModel> \n   [image_hue]: 0x2e6889\n   [ga_prefix]: 101607\n   [id]: 9766400\n   [title]: \U4e3a\U4ec0\U4e48\U6709\U300c\U597d\U5403\U300d\U7684\U8bf4\U6cd5\Uff0c\U6ca1\U6709\U300c\U574f\U5403\U300d\U7684\U8bf4\U6cd5\Uff1f\n   [hint]: \U4f5c\U8005 / \U591a\U90bb\U56fdDuolingo\n   [type]: 0\n   [url]: https://daily.zhihu.com/story/9766400\n</Top_StoriesModel>",
       "<Top_StoriesModel> \n   [image_hue]: 0x8f8164\n   [ga_prefix]: 101507\n   [id]: 9766378\n   [title]: \U5c0f\U4e8b \U00b7 \U6709\U54ea\U4e9b\U8ba9\U4f60\U5fc3\U9178\U7684\U6545\U4e8b\Uff1f\n   [hint]: \U4f5c\U8005 / \U9ec4\U4e0d\U4f1a\n   [type]: 0\n   [url]: https://daily.zhihu.com/story/9766378\n</Top_StoriesModel>",
       "<Top_StoriesModel> \n   [image_hue]: 0x3b3045\n   [ga_prefix]: 101407\n   [id]: 9766350\n   [title]: \U5c0f\U4e8b \U00b7 \U54ea\U4e9b\U65f6\U523b\U8ba9\U4f60\U4f53\U4f1a\U5230\U300c\U77e5\U8bc6\U7684\U5b9e\U7528\U4e0e\U6d6a\U6f2b\U300d\Uff1f\n   [hint]: \U4f5c\U8005 / \U5355\U957f\U6bb7\n   [type]: 0\n   [url]: https://daily.zhihu.com/story/9766350\n</Top_StoriesModel>"
   )
</TestModel3>

因为我们的StoriesModelTop_StoriesModel属于是被TestModel3嵌套的Model,因此我们直接打印TestModel3的对象时storiestop_stories中的数据时打印 得到的是其并未转换为NSString的数据,而是Unicode 转义序列的字符串

如果我们想要得到里面的对象转换为字符串的数据,我们需要事先声明一个嵌套的Model属性

objectivec 复制代码
@property (nonatomic, copy)StoriesModel *t;

然后将大Model中的数组赋值给小Model

objectivec 复制代码
	TestModel3 *testModel = [[TestModel3 alloc] initWithDictionary:responseObject error:nil];
	self.t = testModel.stories[0];
	NSLog(@"%@", self.t);

打印得到:

我们的testModel中的两个NSArray中的对象类型是两个协议,这两个协议的作用是定义了数据模型的接口规范,以便 JSONModel
库知道如何将 JSON 数据映射到具体的对象。通过采用这种方式,可以更灵活地定义数据模型对象,适应不同类型的数据,并在解析 JSON

数据时保持一致性。这使得你可以更容易地将 JSON 数据映射到相应的数据模型对象,以便在应用中使用这些数据。


3.模型导出为NSDictionary或JSON

objectivec 复制代码
ProductModel *pm = [ProductModel new];
pm.name = @"Some Name";

// convert to dictionary
NSDictionary *dict = [pm toDictionary];

// convert to json
NSString *string = [pm toJSONString];

4.设置所有属性可选(所有属性值可以为空)

设置所有属性可选的意义在于即使我们解析Json数据时即使返回为空也不会导致程序崩溃

objectivec 复制代码
@implementation TestModel3
+ (BOOL)propertyIsOptional:(NSString *)propertyName {
    return YES;
}
@end

@implementation StoriesModel
+ (BOOL)propertyIsOptional:(NSString *)propertyName {
    return YES;
}
@end

@implementation Top_StoriesModel
+ (BOOL)propertyIsOptional:(NSString *)propertyName {
    return YES;
}

@end

但是官方建议尽量避免使用该方法(即使要全部属性为可选,也尽量是在每个属性那里标注为Optional)

objectivec 复制代码
@property (nonatomic, strong) NSString<Optional>* optionalProperty;

5.下划线(蛇式)转驼峰命名法

objectivec 复制代码
{
    "order_id": 104,
    "order_product": "Product #1",
    "order_price": 12.95
}
objectivec 复制代码
@interface OrderModel : JSONModel
@property (nonatomic) NSInteger orderId;
@property (nonatomic) NSString *orderProduct;
@property (nonatomic) float orderPrice;
@end

@implementation OrderModel

+ (JSONKeyMapper *)keyMapper
{
    return [JSONKeyMapper mapperFromUnderscoreCaseToCamelCase];
}

@end
相关推荐
SoraLuna8 小时前
「Mac玩转仓颉内测版10」PTA刷题篇1 - L1-001 Hello World
算法·macos·cangjie
iFlyCai8 小时前
Xcode 16 pod init失败的解决方案
ios·xcode·swift
_可乐无糖14 小时前
mac终端使用pytest执行iOS UI自动化测试方法
macos·pytest
后端常规开发人员16 小时前
在 Mac 上使用 Docker 安装宝塔并部署 LNMP 环境
macos·docker·容器·宝塔
郝晨妤18 小时前
HarmonyOS和OpenHarmony区别是什么?鸿蒙和安卓IOS的区别是什么?
android·ios·harmonyos·鸿蒙
Hgc5588866618 小时前
iOS 18.1,未公开的新功能
ios
nukix18 小时前
Mac Java 使用 tesseract 进行 ORC 识别
java·开发语言·macos·orc
CocoaKier19 小时前
苹果商店下载链接如何获取
ios·apple
SoraLuna20 小时前
「Mac玩转仓颉内测版7」入门篇7 - Cangjie控制结构(下)
算法·macos·动态规划·cangjie
Algorithm157621 小时前
mac上使用docker搭建gitlab
macos·docker·gitlab