• 【iOS】JSONModel的基本使用



    前言

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

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


    一、导入JSONModel

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


    二、JSONModel的基本使用

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

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

    1.基本用法

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

    #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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

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

        [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);
        }];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

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


    2.模型集合

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

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

    {
        "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
            }
        ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    Model属性如下:

    //声明网络请求中要接受数据的两个协议
    @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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

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

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

        [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);
        }];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    出现如下结果:

    <TestModel3> 
       [date]: 20231018
       [stories]: (
           " \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",
           " \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",
           " \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",
           " \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",
           " \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"
       )
       [top_stories]: (
           " \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",
           " \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",
           " \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",
           " \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",
           " \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"
       )
    </TestModel3>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

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

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

    @property (nonatomic, copy)StoriesModel *t;
    
    • 1

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

    	TestModel3 *testModel = [[TestModel3 alloc] initWithDictionary:responseObject error:nil];
    	self.t = testModel.stories[0];
    	NSLog(@"%@", self.t);
    
    • 1
    • 2
    • 3

    打印得到:
    在这里插入图片描述

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


    3.模型导出为NSDictionary或JSON

    ProductModel *pm = [ProductModel new];
    pm.name = @"Some Name";
    
    // convert to dictionary
    NSDictionary *dict = [pm toDictionary];
    
    // convert to json
    NSString *string = [pm toJSONString];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

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

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

    @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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

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

    @property (nonatomic, strong) NSString<Optional>* optionalProperty;
    
    • 1

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

    {
        "order_id": 104,
        "order_product": "Product #1",
        "order_price": 12.95
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    @interface OrderModel : JSONModel
    @property (nonatomic) NSInteger orderId;
    @property (nonatomic) NSString *orderProduct;
    @property (nonatomic) float orderPrice;
    @end
    
    @implementation OrderModel
    
    + (JSONKeyMapper *)keyMapper
    {
        return [JSONKeyMapper mapperFromUnderscoreCaseToCamelCase];
    }
    
    @end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    视频号挂公众号链接引流到公众号还能加,好消息来了
    《向量数据库指南》——向量数据库Milvus Cloud快速打造知识库 AI 应用
    DDD实战(一):如何设计分层架构?
    vuex和pinia
    算法高级部分--并查集:方块栈(POJ1988)
    王杰C++day5
    自学SLAM(5)《第三讲:李群和李代数》作业
    Spring Cloud 面试题总结
    使用easypoi-spring-boot-starter 4.1.1导入excel报错NoSuchMethodError和NoSuchMethodError
    java-File类
  • 原文地址:https://blog.csdn.net/weixin_72437555/article/details/133895928