HandyJSON原理

HandyJSON 的优势

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式, 应用广泛. 在 App 的使用过程中, 服务端给移动端发送的大部分都是 JSON 数据, 移动端需要解析数据才能做进一步的处理. 在解析JSON数据这一块, 目前 Swift 中流行的框架基本上是 SwiftyJSON, ObjectMapper, JSONNeverDie, HandyJSON 这么几种.

我们应该如何选择呢?

首先我们应该先明白解析 JSON 的原理. 目前有两个方向.

保持 JSON 语义, 直接解析 JSON.
SwiftyJSON 就是这样的. 本质上仍然需要根据 JSON 结构去取值.

预定义 Model 类, 将 JSON 反序列化类的实例, 再使用这些实例.
这种方式和 OC 中的 MJExtension 的思路是一致的. 在 Swift 中, ObjectMapper, JSONNeverDie, 以及 HandyJSON 做的都是将 JSON 文本反序列化到 Model 类上.

第二种思路是我们熟悉和比较方便的. 和服务端定义好数据结构, 写好 Model 就可以直接解析.

第二种思路有三种实现方式:

完全沿用 OC 中的方式, 让 Model 类继承自 NSObject, 通过 class_copyPropertyList 方法拿到 Model 的各种属性, 从 JSON 中拿到对应的 value, 再通过 OC 中 利用runtime 机制 实现的 KVC 方法为属性赋值. 如 JSONNeverDie.
支持纯 Swift 类, 但要求开发者实现 mapping 函数, 使用重载的运算符进行赋值, 如 ObjectMapper.
获取到 JSON 数据后, 直接在内存中为实例的属性赋值. HandyJSON 就是这样实现的.
第一种方式的缺点在于需要强制继承 NSObject, 这不适用于 struct 定义的 Model. 因为 struct 创建的 Model 不能通过 KVC 为其赋值.
第二种方式的缺点在于自定义 mapping 函数, 维护比较困难.
第三种方式在使用上和 MJExtension 基本差不多, 比较方便. 是我们所推荐的.

HandyJSON 解析数据的原理.

如何在内存上为实例的属性赋值呢?
为属性赋值, 我们需要以下步骤:

获取到属性的名称和类型.
找到实例在内存中的 headPointer, 通过属性的类型计算内存中的偏移值, 确定属性在内存中的位置.
在内存中为属性赋值.
在 Swift 中实现反射机制的类是 Mirror, 通过 Mirror 类可以获取到类的属性, 但是不能为属性赋值, 它是可读的. 但是我们可以直接在内存中为实例赋值. 这是一种思路. 另外一种思路是不利用 Mirror, 直接在内存中获取到属性的名称和类型, 这也是可以的. 目前 HandyJSON 就是利用的第二种方式.

1. 核心原理:绕过反射,直接操作内存

传统的 JSON 库(如 ObjectMapper)依赖 Swift 的 Mirror 反射机制遍历模型属性,但反射存在性能瓶颈且无法直接修改属性值。HandyJSON 通过以下方式实现高效解析:

a. 利用类型元数据(Type Metadata)
  • Swift 编译器会为每个类型生成元数据,包含属性名称、类型、内存偏移量等信息。
  • HandyJSON 直接访问这些元数据,获取属性的名称内存位置,无需通过反射。
  • 例如,结构体的属性在内存中是连续排列的,通过元数据可以计算出每个属性的偏移量。
b. 内存拷贝与指针操作
  • 通过 UnsafeMutablePointer 直接操作模型实例的内存。

  • 将 JSON 值转换为目标类型后,直接写入对应的内存地址。

  • 示例代码逻辑:

    swift

    let offset = getPropertyOffset(from: metadata) // 获取属性偏移量
    let pointer = instancePointer + offset          // 计算属性内存地址
    let value = parseJSONValue(...)                // 解析 JSON 值
    pointer.storeBytes(of: value, as: type)         // 直接写入内存
    

2. 实现步骤详解

a. 类型元数据解析
  • 获取类型信息:通过 type(of:) 或泛型类型参数获取类型的元数据。
  • 解析属性列表:从元数据中提取属性名称、类型、是否为可选类型(Optional)等信息。
  • 处理继承和协议:遍历类型的继承链,确保父类属性也能被正确映射。
b. JSON 到内存的映射
  1. 解析 JSON:将 JSON 数据转换为字典([String: Any])。
  2. 匹配键与属性:将 JSON 的键与模型属性名匹配(支持自定义键名映射)。
  3. 类型转换:将 JSON 值转换为目标属性类型(如 String 转 Int、处理嵌套模型等)。
  4. 内存写入:通过指针将转换后的值写入模型实例的内存。
c. 特殊类型处理
  • 可选类型(Optional):根据 JSON 是否存在键值决定是否写入 nil
  • 枚举(Enum):将 JSON 值映射到枚举的 rawValue 或关联值。
  • 泛型类型:需要特殊处理元数据的动态解析。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/74383.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

信号的产生和保存

信号的产生 信号就是操作系统对用户操作做出的反应,但它的本质就是往操作系统写入信号,这是由操作系统的结构决定的。通过修改比特位来告诉操作系统接收信号和传了几号信号。 也正是因为我们身为用户无法亲自修改内核数据,所以我们需要通过操…

在C++ Qt中集成Halcon窗口并实现跨平台兼容和大图加载

目录 1. Halcon窗口嵌入Qt Widget 2. 处理大图加载 3. 多线程优化显示 4. 跨平台兼容性 1. Halcon窗口嵌入Qt Widget 将Halcon的HWindow控件嵌入到Qt的QWidget容器中,利用系统原生句柄实现跨平台。 #include <HalconCpp.h> #include <QWidget>class HalconWi…

深度学习技术与应用的未来展望:从基础理论到实际实现

深度学习作为人工智能领域的核心技术之一&#xff0c;近年来引起了极大的关注。它不仅在学术界带来了革命性的进展&#xff0c;也在工业界展现出了广泛的应用前景。从图像识别到自然语言处理&#xff0c;再到强化学习和生成对抗网络&#xff08;GAN&#xff09;&#xff0c;深度…

蓝光三维扫描技术:汽车零部件检测的精准高效之选

——汽车方向盘配件、保险杠塑料件、钣金件检测项目 汽车制造工业的蓬勃发展&#xff0c;离不开强大的零部件制造体系作支撑。汽车零部件作为汽车工业的基础&#xff0c;其设计水平、制造工艺、质量控制手段逐渐与国际标准接轨&#xff0c;对于零部件面差、孔位、圆角、特征线…

数据库联表Sql语句建一个新表(MySQL,Postgresql,SQL server)

数据库联表Sql语句建一个新表(MySQL,Postgresql,SQL server) 如果你想基于 SELECT USERS.ID,USERS.NAME,USERS.EMAIL,USERS.ID_CARD,USERS.V_CARD,USERS.ADDRESS,v_card.type,v_card.amount FROM USERS JOIN v_card on USERS.V_CARDv_card.v_card 这个查询结果创建一个新表&am…

六十天前端强化训练之第三十天之深入解析Vue3电商项目:TechStore全栈实践(文结尾附有源代码)

欢迎来到编程星辰海的博客讲解 看完可以给一个免费的三连吗&#xff0c;谢谢大佬&#xff01; 目录 深入解析Vue3电商项目&#xff1a;TechStore全栈实践 一、项目架构设计 二、核心功能实现 三、组合式API深度实践 四、性能优化实践 五、项目扩展方向 六、开发经验总结…

【人工智能】机器学习中的评价指标

机器学习中的评价指标 在机器学习中&#xff0c;评估指标&#xff08;Evaluation Metrics&#xff09;是衡量模型性能的工具。选择合适的评估指标能够帮助我们更好地理解模型的效果以及它在实际应用中的表现。 一般来说&#xff0c;评估指标主要分为三大类&#xff1a;分类、…

不同机床对螺杆支撑座的要求有哪些不同?

螺杆支撑座是机械设备中重要的支撑部件&#xff0c;其选择直接影响到设备的稳定性和使用寿命&#xff0c;尤其是在机床中&#xff0c;不同的机床对螺杆支撑座的要求也是不同的。 1、精度&#xff1a;精密测量用的基准平面和精密机床机械的检验测量设备&#xff0c;需要使用高精…

在Spring Boot中,可以通过实现一些特定的接口来拓展Starter

在Spring Boot中&#xff0c;开发者可以通过实现一些特定的接口来拓展Starter。这些接口允许开发者自定义Spring Boot应用程序的配置和行为&#xff0c;从而创建功能丰富且易于使用的Starter。以下是一些关键的接口&#xff0c;用于拓展Starter&#xff1a; EnvironmentPostPro…

深入理解 tree 命令行工具:目录结构可视化的利器

文章目录 前言1. 什么是 tree 命令&#xff1f;安装 tree 2. tree 的基本用法显示当前目录的树状结构显示指定目录的树状结构 3. tree 的常用选项3.1 显示隐藏文件3.2 排除特定目录或文件3.3 限制递归深度3.4 显示文件大小3.5 显示文件的权限信息3.6 将输出保存到文件 4. 实际应…

Federated learning client selection algorithm based on gradient similarity阅读

基于梯度相似性的联邦学习客户端选择算法 Abstract 摘要introduction**背景****目的****结论****结果****讨论****思路** 链接&#xff1a;https://link.springer.com/article/10.1007/s10586-024-04846-0 三区 Abstract 摘要 联邦学习&#xff08;FL&#xff09;是一种创新的…

【测试工具】如何使用 burp pro 自定义一个拦截器插件

在 Burp Suite 中&#xff0c;你可以使用 Burp Extender 编写自定义拦截器插件&#xff0c;以拦截并修改 HTTP 请求或响应。Burp Suite 支持 Java 和 Python (Jython) 作为扩展开发语言。以下是一个完整的流程&#xff0c;介绍如何创建一个 Burp 插件来拦截请求并进行自定义处理…

网络编程的概念&作用

网络编程是什么&#xff1f; 想象一下&#xff0c;你和朋友在不同的房间里&#xff0c;你们想互相传递纸条聊天。网络编程就像是编写一套规则&#xff0c;让计算机能够通过网络&#xff08;比如互联网&#xff09;互相传递信息。这些信息可以是文字、图片、视频&#xff0c;甚…

航天军工与金融行业 UE/UI 设计:跨越领域的体验革新之道

在数字化时代&#xff0c;用户体验&#xff08;UE&#xff09;和用户界面&#xff08;UI&#xff09;设计成为众多行业提升竞争力的关键因素。航天军工与金融行业虽业务性质差异巨大&#xff0c;但在 UE/UI 设计方面却面临着一些相似挑战&#xff0c;同时也在各自的探索中展现出…

【Git】--- 分支管理

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; Git 本篇博客我们来介绍Git的一个重要功能之一 ---- 分支。我们将讲解关于分支的各种操作&#xff0c;以及如何帮助我们进行开发。 &#x1f3e0; 理解分支…

纯血鸿蒙:中国操作系统自主创新的里程碑

引言&#xff1a;破局者登场 2024 年 10 月&#xff0c;搭载纯血鸿蒙操作系统&#xff08;HarmonyOS NEXT&#xff09;的华为 Mate 70 系列正式发布&#xff0c;首日预约量突破 330 万。这场现象级热度的背后&#xff0c;不仅是消费者对硬件创新的期待&#xff0c;更是中国科技…

二造考试的备考过程中如何保持良好的心态?

在二级造价师考试的备考过程中&#xff0c;保持良好的心态至关重要&#xff0c;以下是一些有效的方法&#xff1a; 树立正确的考试观念 )认识到二级造价师考试是职业生涯中的一个重要环节&#xff0c;但不是唯一的决定因素。把它看作是提升自己专业能力、丰富知识储备的机会&am…

Vue3前端开发:组件化设计与状态管理

Vue3前端开发&#xff1a;组件化设计与状态管理 一、Vue3组件化设计 组件基本概念与特点 是一款流行的JavaScript框架&#xff0c;它支持组件化设计&#xff0c;这意味着我们可以将页面分解成多个独立的组件&#xff0c;每个组件负责一部分功能&#xff0c;通过组件的嵌套和复用…

动手学深度学习11.9. Adadelta-笔记练习(PyTorch)

以下内容为结合李沐老师的课程和教材补充的学习笔记&#xff0c;以及对课后练习的一些思考&#xff0c;自留回顾&#xff0c;也供同学之人交流参考。 本节课程地址&#xff1a;72 优化算法【动手学深度学习v2】_哔哩哔哩_bilibili 本节教材地址&#xff1a;11.9. Adadelta —…

Android Audio基础(13)——audiomixer

在 Android 平台上&#xff0c;音频混合器 AudioMixer 主要用在 AudioFlinger 里&#xff0c;将多路音频源数据混音&#xff08;包括混音、音量处理、重采样及处理声道等&#xff09;。位于 framework 的音频处理模库 libaudioprocessing&#xff08;frameworks/av/media/libau…