Tag: 杰森

在SWIFT中解析JSON – Dennis Vera –中

在SWIFT中解析JSON 在本教程中,我将向您展示如何在Swift中解析JSON。 但是首先,我们需要简要讨论一下应用程序接口 (API)。 API是允许两个软件程序相互通信的代码。 API为开发人员定义了一种从后端系统(数据库)请求服务的程序的正确方式。 这是一个简单的类比,可以帮助您考虑什么是API:将API视为您最喜欢的餐厅中的服务员,您给服务员下订单,几分钟后,他带着您的辣虾炸玉米饼回来。 服务员是使您连接到厨房的使者,就像一个API。 您从API请求数据,然后返回该位置可用的数据。 为了实现这种代码交换,您需要一种安全的方式来捕获数据,并且该数据将以JSON文件表示,这是业界首选的格式。 还有一些XML文件可以实现此目的,但是如果将XML文件的语法与JSON文件进行比较,您将很快了解为什么首选JSON。 什么是JSON? 为什么JSON是数据传输的首选数据格式? JavaScript Object Notation (JSON)是一种轻量级的数据交换格式。 人类很容易读写。 机器很容易解析和生成。 它基于JavaScript编程语言的子集。 JSON是一种文本格式,它完全独立于语言,但是使用许多语言的程序员熟悉的约定。 这些属性使JSON成为理想的数据交换语言。 现在该解析一些JSON了,这意味着对其进行处理并检查其内容。 在Swift中这并不容易,因此出现了许多帮助程序库,这些程序库对我们来说很繁重。 我们现在将使用其中之一:从GitHub下载该项目的文件,然后查找名为SwiftyJSON.swift的文件。 添加您的项目。 SwiftyJSON使我们能够以一种非常直观的方式阅读JSON:您可以将几乎所有内容都有效地视为字典,因此,如果您知道有一个名为“元数据”的值,其中包含另一个名为“ name”的值,而该值又包含另一个名为“ name”的值dog1”,则可以使用json [“ metadata”] [“ dog1”] [“ name”] [“ breed”]来获取数据,然后使用string属性将其作为Swift值来请求。 使用SwiftyJSON解析JSON文件: 在您的项目中安装SwiftyJSON。 创建一个UITableViewController; 我们将在表视图控制器上打印数据。 使用准确的数据在下面创建一个JSON文件(请参见下文)。

使用Decodable进行JSON解析

JSON是通过网络发送的最常用的数据格式。 在Swift 4之前,使用JSON是iOS的头疼事。 Apple提供了JSONSerialization类来处理JSON响应,但是JSONSerialization的问题在于,它只是将字符串响应转换为合适的NSArray或NSDictionary对象。 将字典转换为对象快速类别或目标C类是我们的责任。 所有这些手动工作都由一些非常流行的第三方库(如SwiftyJSON , JSONShootout等)解决。SwiftyJSON是我的最爱之一。 所有这些库在内部都使用反射,将JSONSerialization的输出转换为对象。 Swift 4通过Codable使一切变得简单,并终止了这些第三方库的使用。 可编码使我们能够解码和编码对象。 它可以与类,结构以及枚举一起使用。 在本教程中,我们将专注于解码响应并将其转换为快速对象。 以下是我们将在本教程中使用的一些关键术语。 关键术语 可腐烂 协议是可解码的。 如果要从JSON解码对象,则您的类或结构需要符合此协议。 2.可 编码 该协议是可编码的。 如果要将对象编码为Data,则您的类或结构需要符合此协议。 3.可 编码 可编码是可编码和可解码的组合协议。 如果您需要在应用程序中对对象进行解码和编码。 与其同时符合可编码性和可解码性,不如使其符合可编码性。 4. JSONDecoder 用于从JSON数据解码对象。 注意。 您的类或结构必须符合Decodable协议。 5. JSONEncoder 用于将对象编码为数据。 注意。 您的类或结构必须符合Encodable协议。 可编码有一些限制。 它仅限于某些基本数据类型,而有些则是高级数据类型。 这是我们在声明支持可编码的类时可以使用的所有数据类型的列表。 让我们从例子开始。 解析简单对象 班级人员:可腐烂{ 变量名称:字符串 变量年龄:整数 } 让jsonData =“”“ { “名称”:“ John Doe”, “年龄”:24 } […]

在Swift中实现快速JSON解析的道路

在过去的几年中,我已经编写了很多库。 但是没有一个图书馆比BSON更具教育性和趣味性。 BSON是MongoDB制作的一种格式,类似于JSON,但为二进制。 它可以非常有效地进行读写。 我们的BSON实现采用了我们收到的原始缓冲区,并且仅使用原始缓冲区就可以高性能获取任何您想要的东西。 因此,如果经常从套接字接收此数据,则无需复制缓冲区。 当我尝试使用JSON时,结果截然不同。 BSON是一种聪明的格式 Document的格式大致与此类似,但采用二进制形式: [(BSONType, KeyString, BSONValue)] 。 任何类型为空的值都为空(否)。 任何具有恒定长度的类型(Int,布尔值)都可以进行内联解析和变异,而不会遇到任何麻烦。 如果您有一个长度可变的类型,例如数组,(sub)Document,String或Binary Blob,则情况会稍有变化。 这些值在数据前都有一个32位整数,因此,如果您确定不需要此键,则可以跳过该键而不必读取实际值。 这样,如果您有一个具有5个键的用户,而只需要键4,则在4之前,几乎不会花任何力气在键5上花费任何精力。 在我们的库中,我们保留了所有类型的少量缓存以及在它们处找到的偏移量。 因此,如果我们决定需要键3,则甚至无需在此之前搜索键。 该缓存是一个很小的优化,但实际上可以在更大的数据集中获得回报。 JSON是慢速格式 虽然对人类来说解析起来非常容易,但对于计算机而言则相反。 如果您收到带有嵌套对象的对象,则计算机需要先解析所有内容,然后才能知道当前对象的结束位置。 仅以原始格式将JSON存储在内存中是提高性能的好主意。 因此,我开始考虑BSON,得出的结论是,在这里,我们也可以选择不复制整个String,而是将缓存保留到原始缓冲区。 这样,如果您不需要JSON中的所有键和值,则几乎不需要花费任何精力来读取那些未使用的值。 因此,我开始考虑构建缓存的想法,该缓存几乎与BSON相同,但有一些小的更改。 布尔值存储为单独的类型(boolTrue和boolFalse)。 如果布尔值的文本已经在索引中被扫描,则无需解析。 字符串不能包含转义字符。 如果未对String进行转义,则不必执行这些转义的检查/转换。 我们需要检查它,以查看转义字符是否始终以转义符结尾。 数字根据文字中的字符将其类型存储为整数或浮点类型。 这可以减轻解析。 字符串和数字可以延迟解析,我们不需要复制它们。 这主要节省了内存使用。 因此,在实现此功能之后,我很高兴看到缓存在相同的JSON数据方面优于Foundation。 但是我渴望更多。 比BSON更好的缓存 当我查看事件探查器时,我注意到几乎所有性能都是要读取和写入缓存。 我认为这很有意义,但是很多内存操作不需要这么重。 那时我想起了缓存的结构。 缓存将为数组和对象创建键和值的单独列表。 这意味着将为每个对象和数组进行新的内存分配。 每次在Codable中遍历该结构时,都需要将其加载到您的CPU中。 因此解决方案是减少内存使用量,但是如何呢? 我想到的是缓存的单个指针。 如果我将所有数据存储在单个缓冲区中(例如BSON格式本身),则可以轻松遍历它们。 未使用的数据将几乎无害。 经过3点的工作,缓存已完成。 结果是惊人的。 测试使用初始缓存在构建中花费了25ms,而使用新缓存仅花费了17ms。 缺点 […]

在Swift中解析JSON的正确方法

解析JSON的正确方法是使用Codable。 但是Codable的问题在于,如果您有嵌套的JSON,则必须编写额外的Codable结构或编写自定义初始化程序。 这就是为什么许多开发人员选择使用诸如SwiftyJSON之类的第三方解决方案的原因。 但这就是失败的道路。 让我们对其进行修复,并结合SwiftyJSON和Codable的最佳部分来制作下一个JSON解析库。 这个主意 有两种从JSON解析嵌套结构的方法:创建额外的Codable结构或创建自定义初始化程序。 让我们考虑一下如何实现两者的自动化。 第一种方法可以通过代码生成实现自动化。 但是要获得它,要花很多时间才能使它起作用,并且您必须具有一些JSON的形式化描述。 让我们仔细看看创建自定义初始化程序的第二种方法。 简要地说,我们必须描述每个嵌套级别的编码键。 然后,我们可以使用这些编码键来创建嵌套容器。 看一下示例JSON: 让json = [ “容器”: [ “对象”:[ “名称”:“阿纳金·天行者”, “ alias”:“ Darth Vader”, “职业”:“西斯黑暗之王”, “年龄”:42岁 ] ] ] 让jsonData =尝试JSONSerialization.data(withJSONObject:json,选项:[]) 为了解析它,我们必须创建一个包含额外编码键的结构: struct Human:可编码{ 命名:字符串 让别名:字符串 让职业:字符串 年龄:整数 枚举ContainerKeys:字符串,CodingKey { 箱子容器 } 枚举ObjectKeys:字符串,CodingKey { 案例对象 } public init(来自解码器:Decoder)抛出{ 让容器=尝试解码器。容器( keyedBy:ContainerKeys.self ) 让嵌套=尝试container.nestedContainer( keyedBy:ObjectKeys.self, forKey:.container […]

天哪,Codable太棒了

在上一篇文章中,我用滚动视图描述了我的短暂尝试,其中包括以下部分: 为了帮助您了解所见,我在Intertubes上寻找了引人注目的数据馈送示例,并最终选择了USGS地震馈送。 只是。 因为。 为了整理提要,我认为我可以快速给新的Swift Codable协议打转,那时候我就知道了Frickin 很棒的 Codable是什么。 但这是下一篇文章。 抓紧。 您现在可以停止收紧。 这是那篇文章 。 我们将深入研究Xcode 9和Swift 4的Codable功能。 我们将从我在滚动视图文章中提到的GeoJSON feed示例开始,然后使用RolePlayingCore Github存储库更深入地研究更多示例。 首先:简单地遵循Codable 我从一个仅包含几个项目的基本结构开始,然后迅速使用嵌套结构和枚举来构建它。 GeoJSON提要足够简单( 请参阅此处的链接 ),Swift提供的自动生成的构造函数和编码键非常有用。 我总结了一下,涵盖了大约一半的属性,大部分是有趣的属性: 现在,我没有尝试解决使用JSON可能引起的一些棘手的问题。 但这主要是因为该示例不需要它,无论如何,我花更多的真实代码(例如RolePlayingCore GitHub存储库)来揭示有关Codable的更深层真相的旅程很快就会花光。 “所有软件在编写后即会成为旧版。”-实用程序设计师Andrew Hunt和David Thomas 好的, 很好 。 那也不是真实的代码,但是由于我已经花了一些时间在JSON解码上,所以我在六个月的令人震惊的时间内建立了相当多的“旧版”代码,并且为后续工作提供了便利更深入到Codable。 所以。 CodingKeys,解码和编码,天哪! 当您必须处理带有下划线或空格,拼合或不拼合嵌套类型的名称,或转换非本地JSON类型(例如发给子级Date)的名称时 ,您突然不得不为Codables添加样板。 但是,这非常简单,我几乎想跳过它,并继续处理更棘手的问题。 但。 让我们。 让我们从使用序列化已经可以与JSON一起使用的现有类型开始。 所以。 假设某些D&D 类特征,我们可能具有: 注意TODO。 好。 呼吁采取行动! 为这项开源计划做出贡献! 帮助我致富! 帮助我舒适地退休! 好,好,回到现实… 相应的JSON格式可能如下所示: 在Swift […]

Swift中可用的数据序列化格式

大家好, 在本文中,我想向您展示JSON序列化的许多替代方法。 它们都有优点和缺点,但至少您应该对它们有所了解。 什么是序列化? “在 计算机科学中 ,在数据存储的上下文中, 序列化 是将 数据结构 或 对象 状态转换为可以稍后存储或传输和重构的格式 的过程 。”还有一个反序列化概念,它会将序列化数据反转为我们的自定义对象。 我已经写了一篇关于它的文章。 我们在哪里使用序列化? 通过网络传输数据。 存储数据。 远程过程调用。 (RPC) JSON , XML , protobuf , YAML , BSON , MessagePack是数据序列化的示例。 我猜最知名的是移动应用程序开发中的JSON和XML。 与JSON相比,使用JSON的首选多于XML,因为JSON的可读性更好,而且尺寸更小。 JSON (JavaScript对象表示法):它是人类易读的并且易于由机器解析和生成,这就是为什么它被选中的原因。 但是在我看来,可读的响应格式对于检查数据类型非常重要,这使得JSON更加紧密。 Swift有很多第三方库可用于JSON序列化和反序列化。 您可以在这里检查。 在我以前的文章中,您还可以看到其中的一些示例。 //简单的JSON格式示例 { “名称”:“阿里可以” “姓”:“巴图尔” “年龄”:29 } XML (可扩展标记语言):定义了一组规则,用于以人类可读和机器可读的格式对文档进行编码。 XML难以辨认且复杂,因此不太受欢迎。 解析它还需要比JSON和其他方法更多的工作。 您可以在此处找到第三方解析器。 这里也有对此的SDK(基础)支持。 Ali Can 巴图尔 […]

使用中间类型在Swift中解码JSON

基础 要解码JSON结构并将应用程序中的模型编码回JSON,您可以使模型符合Swift Codable协议。 这是另外两个协议的组合: Decodable和Encodable 。 这对于简单的JSON数组和字典非常有用,例如: 让json =“”“ [ { “名称”:“年度旅行保险”, “ paymentFrequency”:“每年”, “ description”:“全年安全旅行。” }, { “名称”:“汽车保险”, “ paymentFrequency”:“每月” } ] “”“ .data(使用:.utf8)! 您可以使模型符合Codable (或Decodable )协议: struct BankProduct:可编码 { 变量名称:字符串 var paymentFrequency:付款频率 var说明:字符串? 枚举PaymentFrequency:字符串,可编码{ 每月个案 每年一次 } } 只要JSON数组中没有其他不代表我们模型的元素,所有内容都会自动解码。 否则,解码将失败。 这意味着我们可以在JSON结构的每个元素中添加额外的键,但是键name和category应始终位于该元素中,因为它们在我们的模型中不是可选的。 在此示例中,还添加了一个枚举,因此您可以看到,只要枚举符合(De)Codable协议且枚举的大小写名称与中的字符串相同,它就会自动将JSON转换为正确的大小写。 JSON。 否则,您需要为案例提供一个rawValue 。 我们可以使用以下方法从JSON创建对象: 让解码器= JSONDecoder() 让产品=尝试解码器。解码([BankProduct] .self,来自:json) 当JSON的键名与模型中属性的名称不匹配时,我们需要一个名为CodingKeys的嵌套枚举,其枚举类型应符合CodingKey协议,它的String rawValue类型。 枚举应包含所有键,即使在模型和JSON中具有相同名称的键也是如此。 […]