JSONKit 1.6

JSONKit 1.6

测试已测试
Lang语言 MUMPSMUMPS
许可证 Apache 2
发布最新发布2023 年 9 月

由 . 维护



  • 作者:
  • John Engelhart

JSONKit

JSONKit 采用双重许可,要么根据 BSD 许可证的条款,要么根据 Apache 许可证第 2.0 版的条款。
版权 © 2011,John Engelhart。

非常高性能的 Objective-C JSON 库

更新:(2011/12/18)下面的基准测试在苹果的 NSJSONSerialization 可用之前进行(截至 Mac OS X 10.7 和 iOS 5)。显然的问题是:哪个更快,NSJSONSerialization 还是 JSONKit?根据 此网站,JSONKit 比 NSJSONSerialization 更快。使用报告的数字进行一些快速的计算,JSONKit 似乎比 NSJSONSerialization 快 25% 到 40%,这是一个相当大的差异。

解析 序列化
Deserialize from JSON Serialize to JSON
比二进制 .plist快 23% 比二进制 .plist快 549%
  • 在拥有 2.66GHz Core 2 的 MacBook Pro 上进行了基准测试。
  • 所有 JSON 库都使用 gcc-4.2 -DNS_BLOCK_ASSERTIONS -O3 -arch x86_64 编译。
  • 时间结果是对 getrusage 报告的用户加系统时间的 1,000 次迭代的平均值。
  • 使用的 JSON 是来自 samsoffes / json-benchmarkstwitter_public_timeline.json
  • 由于 .plist 格式不支持序列化 NSNull,原始 JSON 中的 null 值被更改为 "null"
  • 实验性 分支包含了 gzip 压缩更改。
    • JSONKit 在运行时自动链接到 libz.dylib,无需手动链接。
    • 如果检测到 gzip 签名头,解析 / 反序列化将自动解压缩缓冲区。
    • 您可以通过传递 JKSerializeOptionCompress-JSONDataWithOptions:error: 来压缩 / gzip 序列化的 JSON。

JSON 与 PLIST,终极对决 对常见的 JSON 库进行了基准测试,并将它们与苹果的 .plist 格式进行了比较。


JavaScript对象表示法,或JSON,是一种轻量级、基于文本的序列化格式,用于结构化数据的表示,被许多基于Web的服务和API使用。它由RFC 4627定义。

JSON提供了以下原始数据类型

  • null
  • 布尔值 truefalse
  • 数字
  • 字符串
  • 数组
  • 对象(又称关联数组、键/值散列表、映射、字典等)

这些原始数据类型映射到以下Objective-C Foundation类

JSON Objective-C
null NSNull
truefalse NSNumber
数字 NSNumber
字符串 NSString
数组 NSArray
Object NSDictionary

JSONKit内部使用Core Foundation,并假定Core Foundation等于每个等效的基本类型,即 CFString 等同于 NSString.

在此文档中,“必须”,“禁止”,“必需”,“应当”,“不应”,“应该”,“不应当”,“推荐”,“可能”和“可选”等关键词将按照RFC 2119中的描述进行解释。

JSON到Objective-C原始数据类型映射的详细信息

  • JSON规范对Unicode的细节和要求有些含糊不清,并且未指定如何处理Unicode问题和错误。大部分的含糊源于对RFC 4627第二章的解读和范围,特别是编码:JSON文本“应当”使用Unicode进行编码。作者认为,根据RFC 4627,JSON实现必须遵循Unicode标准中指定的要求,尤其是Unicode标准的“一致性”章节,该章节指定了与处理、解释和操作Unicode文本相关的要求。

    JSONKit的默认行为是严格遵循RFC 4627。作者认为,根据RFC 4627,JSON应使用Unicode编码,因此不符合Unicode标准的非法Unicode是不合法的JSON。因此,JSONKit将不接受包含非法Unicode的JSON。默认的严格行为表示没有启用JKParseOptionLooseUnicode选项。

    当启用JKParseOptionLooseUnicode选项时,JSONKit遵循Unicode 6.0标准第三章“一致性”中给出的规范和建议,特别是3.9“Unicode编码形式”。一般而言,对于遇到的任何非法Unicode,使用Unicode代码点U+FFFD进行替换。JSONKit试图遵循推荐的用于U+FFFD的最佳实践:用单一个U+FFFD替换非法子序列的每个最大子部分。

    以下Unicode代码点被视为非法Unicode,如果启用了JKParseOptionLooseUnicode,将用U+FFFD替换

    U+0000.
    U+D800U+DFFF,包括
    U+FDD0U+FDEF,包括
    U+nFFFEU+nFFFF,其中n是从0x00x10

    代码点U+FDD0U+FDEFU+nFFFEU+nFFFF(其中n是从0x00x10)被Unicode标准定义为非字符,并且“不应”交换。

    针对代码点 U+0000,它是一种合法的Unicode编码,将做出例外。原因是这个特定的代码点被C字符串处理代码用来指定字符串的结尾,而任何这样的字符串处理代码都将在代码点 U+0000 发生的地方错误地停止处理字符串。虽然关于这个问题,不同的人可能会有不同的看法,但作者认为允许包含 U+0000 的JSON字符串所带来的风险大于其好处。允许字符串中的 U+0000 未经过更改地出现的一个风险是,它可能会以微妙地改变字符串语义的方式创造出安全风险,这可能被恶意攻击者利用。这与从Unicode文本中任意删除字符的问题类似。

    RFC 4627 允许这些限制在4章中的解析器部分: 实现可以限制字符串的长度和字符内容。虽然 Unicode标准 允许对原始的JSON进行变化(例如用 U+FFFD 替换不规范的Unicode),但 RFC 4627 对这个问题没有明确说明。作者认为,根据 RFC 4627 中第3节 – 编码部分的规定, JSON文本必须以Unicode进行编码。这意味着这样的变化不仅允许,而且任何严格遵守 RFC 4627 的JSON实现都必须预期这种变化。作者有责任指出,这种观点和解释可能不为其他人所接受,并且事实上可能是少数人的观点和解释。您应该意识到,对原始JSON的任何修改都可能会微妙地改变其语义,因此可能会对消费最终结果的内容产生安全相关的含义。

    值得注意的是,JSONKit不会删除正在解析的JSON中的字符,因为这是由 Unicode标准规定的需求。更多详细信息可以在 Unicode安全常见问题解答Unicode技术报告 #36 - Unicode安全考虑 中找到,特别是关于 非视觉安全 的章节。

  • JSON规范 没有指定JSON String值的具体细节或要求,除了这些字符串必须由Unicode代码点组成外,也没有规定应该如何处理错误。虽然JSONKit会在上述关于Unicode的合理警告范围内尽最大努力保留解析的JSON String,但它无法保证 NSString 会保留原始JSON String的精确Unicode语义。

    JSONKit未对解析后的JSON字符串进行任何形式的Unicode规范化,但不能保证在实例化NSString对象时使用的解析后的JSON字符串不会进行Unicode规范化。可能对JSON字符串进行额外限制或另作处理,使该JSON字符串与其实例化的NSString对象的对应关系不再是双射的。换句话说,JSONKit不能保证在将JSON字符串往返转换为NSString对象,然后再将其转换回JSON字符串时,这两个JSON字符串将完全相同,尽管在实际情况中它们确实是。在这里,“完全相同”意味着位对位相同。JSONKit甚至不能保证这两个JSON字符串将是Unicode等效的,尽管在实际情况中它们将是这样,也最可能是导致往返的JSON字符串不再位对位相同的根本原因。

  • JSONKit将“true”和“false”映射到CFBooleankCFBooleanTruekCFBooleanFalse。从概念上讲,可以将CFBoolean值视为NSNumber类的对象。使用CFBoolean的好处是,truefalse的JSON值可以在不进行转换或不提升到值为01NSNumber的情况下进行往返序列化和反序列化。

  • JSON规范没有指定JSON Number值的详细信息或要求,也没有指定如何处理由于转换而产生的错误。通常,JSONKit不会接受包含它无法错误或精度损失地转换的JSON Number值的JSON。

    对于非浮点数(即不包含“.”或“e|E”的JSON Number值),JSONKit无论目标架构是32位还是64位,都使用64位的C原始类型。对于无符号值(即不以“-”开头),这允许值为“264-1”,对于负值,为“-263”。作为一个特殊情况,JSON Number“-0”被当做浮点数来处理,因为底层的浮点原始类型可以表示负零,而底层的补码非浮点原始类型则不能。超出这些限制的Number值包含的JSON将无法解析,并可选择返回一个NSError对象。函数strtoll()strtoull()用于执行转换。

    C double 原始类型,或称为 IEEE 754 双精度 64 位浮点格式,用于表示浮点 JSON Number 值。包含无法表示为 double(即,由于溢出或下溢)的浮点 Number 值的 JSON 将无法解析,并且可以选择性地返回一个 NSError 对象。使用函数 strtod() 执行转换。请注意,JSON 标准不允许无穷大或 NaN(不是一个数字)。浮点值的转换和操作不是一件简单的事情。不幸的是,RFC 4627 对如何处理此类详细信息保持沉默。您不应依赖或期望在经过回路三次的浮点值具有相同的文本表示或甚至可以相等。即使在 JSONKit 同时用作解析器和 JSON 创建者的情况下也是如此,更不用说在不同系统和实现之间传输 JSON 的情况了。

  • 对于 JSON 对象(或 JSONKit 术语中的 NSDictionary),RFC 4627 表示 "对象中的名称应该是唯一的"(注意:name 在 JSONKit 术语中是 key)。目前,当 JSON 包含在对象中名称不唯一的情况时,JSONKit 的行为是 未定义的。但是,JSONKit 当前试图遵循“解析出的最后一个键/值对是所选的”政策。这种行为尚未最终确定,不应依赖。

    之前提到的有关 JSON 字符串的限制对 JSON 对象有重要的影响,因为 JSON 字符串用作 keyJSON 规范 没有指定用于 JSON 对象中的 keys 的 JSON 字符串的详细信息或要求,例如两个 keys 比较相等的含义。不幸的是,因为 RFC 4627 表示 "JSON 文本应使用 Unicode 编码",这意味着必须使用 Unicode 标准 解释 JSON,且 Unicode 标准 允许具有不同 Unicode 代码点的字符串“比较相等”。JSONKit 仅使用 NSString 管理已解析的 JSON 字符串。由于 NSStringUnicode 为其基础,存在 NSString 可能会微妙且静默地将原始 JSON 字符串中的 Unicode 代码点转换为 Unicode 等效字符串的可能性。因此,当 JSON 字符串用作 JSON 对象中的 keys 且可能是 Unicode 等价但不是二进制等效时,JSONKit 的行为是 未定义的

    另请参阅
        W3C - 字符串身份匹配和字符串索引的要求

Objective-C 到 JSON 原始映射的详细信息

  • 在序列化时,顶层容器及其所有子容器在枚举过程中必须严格保持不变性。这个属性被用于实现某些优化,例如,如果一个特定的对象已经被序列化,那么可以重复使用之前序列化的UTF8字符串的结果(即,简单地复制先前序列化的UTF8字符串,而不是再次执行全部序列化工作)。虽然这可能只对那些正在用运行时或从JSONKit序列化类继承的自定义类来进行非常不寻常的事情的人感兴趣(即,每次序列化输出请求自定义对象的值时,其值都发生变化的自定义对象),但它也涵盖了在枚举过程中任何要序列化的对象发生变化的情形(即,由另一个线程引起的变化)。JSONKit请求对象值次数是非确定的,从最少一次到其在序列化JSON中出现的次数,因此,对象绝对不能依赖于每次在序列化输出中出现时都接收到请求其值的消息。如果违反这些要求,行为是未定义的。

  • 要序列化的对象必须是无环的。如果要序列化的对象包含循环引用,行为是未定义的。例如,...

    [arrayOne addObject:arrayTwo];
    [arrayTwo addObject:arrayOne];
    id json = [arrayOne JSONString];

    将导致未定义的行为。

  • NSString对象的的内容以UTF8编码并添加到序列化的JSON中。JSONKit假定NSString产生的UTF8 Unicode格式良好,不进行额外的验证。当启用JKSerializeOptionEscapeUnicode时,JSONKit将编码可以编码为单个UTF16代码单元的Unicode码点为\uXXXX,并将需要UTF16代理对的Unicode码点编码为\uhigh\ulow。虽然JSONKit尽力序列化NSString对象的内容,但题目为RFC 4627要求除外,但NSString类使用Unicode Standard作为其表示字符串的基础。你应该注意,Unicode Standard定义了字符串等效性,即比较相等的字符串不要求逐比特相同。因此,有可能NSString以这样一种方式改变字符串,使其在不同的字符中,但不是与原始字符串逐比特相同的Unicode等效

  • NSDictionary 类允许任何对象作为 key 使用,对象可以是任何类。然而,JSON 只允许使用 String 作为 keys。因此,如果 JSONKit 在序列化过程中遇到包含非 NSString 对象的 NSDictionary,将会报错。更具体地说,key 必须在发送 -isKindOfClass:[NSString class] 时返回 YES

  • 如果 JSONKit 在序列化过程中遇到非 NSNullNSNumberNSStringNSArrayNSDictionary 类对象,将会出错。更具体地说,如果这些之前提到的类对象中的 -isKindOfClass: 返回 NO,JSONKit 将出错。

  • JSON 不允许使用 ±Infinity±NaN 这样的数字。因此,如果 JSONKit 在序列化过程中遇到包含这些值的 NSNumber,将会报错。

  • 使用 [NSNumber numberWithBool:YES][NSNumber numberWithBool:NO] 创建的对象将分别映射到 JSON 类型的 truefalse。更具体地说,一个对象必须与 kCFBooleanTruekCFBooleanFalse 指针相等(即 if((id)object == (id)kCFBooleanTrue)),才能映射到 JSON 的 truefalse 值。

  • 非布尔型的 NSNumber 对象(如上定义)将发送 -objCType 来确定它们所代表的 C 原始类型。那些响应为 cislq 集合中的类型的,被视为 long long;响应为 CISLQB 集合中的类型的,被视为 unsigned long long;响应为 fd 集合中的类型的,被视为 double。响应为上述类型集合之外类型的 NSNumber 对象将导致 JSONKit 出错。

    更具体地说,使用CFNumberGetValue(object, kCFNumberLongLongType, &longLong)函数来获取有符号和无符号整数的值,使用-objCType指定方法来判断结果是有符号还是无符号。对于浮点数,使用CFNumberGetValuekCFNumberDoubleType参数来获取值。

    使用printf的格式转换指定符%.17g将浮点数转换为十进制表示形式。理论上,这允许表示多达float,或者IEEE 754 32位单精度浮点数的精度。这意味着在实践中,double值转换为float值时会有精度损失。关于RFC 4627标准在处理浮点数方面的规定是沉默的,作者发现现实中JSON实现对此问题的处理方式差异很大。此外,格式转换指定符%g可能将可以精确表示为整数的浮点值转换为没有包含.e的文本表示(即在转换为整数,例如5.0变成5)。由于许多关于浮点值转换和操作的问题,你不应期望或依赖于浮点值保持其全部精度,或者在进行往返转换时相等。

报告错误

请使用github.com JSONKit问题跟踪器来报告错误。

作者请求你,除非首先手动验证这是JSONKit的真实问题,且根据C99语言规范,如果是适用的话,不是"合法"的C代码,否则不要就clang静态分析工具报告的问题向JSONKit提交错误报告。如果clang静态分析工具报告的问题是JSONKit的非真实问题,且根据C99语言规范是合法代码,那么提交错误报告或提出投诉的正确地方是向clang静态分析工具的开发者提交。

重要细节

  • JSONKit不是为与Mac OS X垃圾收集一起使用而设计的。使用-fobjc-gc编译JSONKit时的行为是未定义的。非常不可能支持Mac OS X垃圾收集。

  • JSONKit 不设计用于与Objective-C 自动引用计数 (ARC)一起使用。当使用-fobjc-arc编译JSONKit时,其行为是未定义。当没有ARC编译的JSONKit与带有ARC编译的代码混合使用时,其行为在规范性上是未定义,因为在此期间还没有进行任何分析来确定此配置的安全性。目前没有计划在JSONKit中支持ARC。尽管如此,由于许多与不支持Mac OS X垃圾回收相同的理由,ARC被支持的几率极低。

  • JSONKit 将要解析的JSON必须以Unicode编码。在极不可能的情况下,如果你得到了未以Unicode编码的JSON,你必须首先将JSON转换为Unicode,最好是UTF8编码。实现这一目标的一种方法是用NSString类的方法-initWithBytes:length:encoding:-initWithData:encoding:

  • 内部,使用的是低级别的解析引擎,仅使用UTF8编码。方法JSONDecoder中的-objectWithData:接受NSData对象作为其参数,并假定包含在NSData中的原始字节数据是以UTF8编码的,否则行为是未定义

  • 同时使用相同的JSONDecoder实例在多个线程中是不安全的。如果你要在多个线程间共享JSONDecoder,你必须负责添加互斥锁(mutex)屏障,以确保在任何时候只有一个线程使用共享的JSONDecoder对象来解码JSON。

关于速度的建议

  • 启用预处理器标志NS_BLOCK_ASSERTIONS。JSONKit在内部大量使用了NSCParameterAssert()来确保各种参数、变量以及其他状态只包含合法和预期的值。如果断言检查失败,它将引发导致程序通常终止的运行时异常。这些检查和断言是有代价的:它们需要执行时间,并不会对工作产生影响。启用NS_BLOCK_ASSERTIONS是完全安全的,因为JSONKit始终进行正确运行所需的检查。使用NSCParameterAssert()执行的检查是完全可选的,并且通常用于希望进行更多完整性检查的“调试”构建。虽然具体情况可能会有所不同,但作者发现,将-DN_BLOCK_ASSERTIONS添加到-O2优化设置中,通常可以带来约7-12%的性能提升。

  • 由于最低级别的解析引擎专门使用 UTF8 字节流,所以任何未以 UTF8 编码的东西都必须首先转换为 UTF8。虽然JSONKit为NSString类提供了扩展,这些扩展使得将包含在NSString中的JSON方便地转换为其他形式,但这种便利是有代价的。JSONKit必须分配足够大的NSMutableData来自动释放字符串的UTF8转换,然后在开始解析之前将字符串转换为UTF8。这既占用内存又耗费时间。一旦解析完成,JSONKit将自动释放的NSMutableData长度设置为0,这使得NSMutableData可以释放内存。这有助于最小化占用的但直到自动释放池结束前不可用的内存量。因此,如果速度和内存使用是首要任务,你应尽可能避免使用NSString的便利方法。

  • 如果你从网络服务器接收JSON数据,并且能够确定网络服务器返回的原始字节数据是以UTF8编码的JSON,你应该使用JSONDecoder方法的-objectWithUTF8String:length:,它立即开始解析字节指针。在实际应用中,几乎每个将JSON转换为Objective-C对象的JSONKit方法最终都会调用这个方法来执行转换。

  • 如果你使用NSURL类族提供的各种方法之一来从网络服务器接收JSON结果,这些方法通常以NSData对象的形式返回结果,并且你能够确定包含在NSData中的原始字节数据是UTF8编码的,那么你应该使用JSONDecoder方法的objectWithData:NSData方法的-objectFromJSONData。如果你将要转换大量JSON,更好的选择是一旦实例化一个JSONDecoder对象,就使用同一个实例对象执行所有的转换。这样做有两个好处

    1. NSData方法的-objectFromJSONData会创建一个自动释放的JSONDecoder对象来执行一次性的转换。通过一次实例化一个JSONDecoder对象并多次使用objectWithData:方法,你可以避免这种开销。
    2. 重用了之前JSON转换的实例对象缓存。如果你要转换的JSON非常相似,这不仅可以提高性能,还可以减少内存使用量。一个典型的例子可能是在定期间隔内转换包含实时状态更新的JSON。
  • 平均而言,当将NSDictionaryNSArray序列化到JSON时,JSONData…方法的性能几乎比JSONString…方法提高近四倍。这种速度差异完全是由于NSString实例化的开销造成的。

  • 尽可能使用 NSData 而不是 NSString 方法来处理 JSON。这避免了 NSString 进行对象接口转换时产生的显著转换开销,对象接口转换是为了提供其内容的对象接口。对于许多用法,使用 NSString 是不需要的,并且会导致无效的工作 – 例如,使用 JSONKit 将 NSDictionaryNSArray 序列化为 NSString。然后,这个 NSString 被传递到一个方法中,该方法将 JSON 发送到 web 服务器,并且这不可避免地需要将 NSString 转换为 NSData,然后才能发送。在这种情况下,直接将集合对象序列化为 NSData 将避免对 NSString 对象进行的无必要转换。

解析接口

JSONDecoder 接口

objectWith… 方法返回不可变集合对象,而它们各自的 mutableObjectWith… 方法返回可变集合对象。

注意: NSData 对象包含的字节必须使用 UTF8 编码。

重要: 如果 parseOptionFlags 不是一个有效的值,方法将抛出 NSInvalidArgumentException
重要: 如果 stringNULLobjectWithUTF8String:mutableObjectWithUTF8String: 将抛出 NSInvalidArgumentException
重要: 如果 jsonDataNULLobjectWithData:mutableObjectWithData: 将抛出 NSInvalidArgumentException

+ (id)decoder;
+ (id)decoderWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
- (id)initWithParseOptions:(JKParseOptionFlags)parseOptionFlags;

- (void)clearCache;

- (id)objectWithUTF8String:(const unsigned char *)string length:(size_t)length;
- (id)objectWithUTF8String:(const unsigned char *)string length:(size_t)length error:(NSError **)error;
- (id)mutableObjectWithUTF8String:(const unsigned char *)string length:(size_t)length;
- (id)mutableObjectWithUTF8String:(const unsigned char *)string length:(size_t)length error:(NSError **)error;

- (id)objectWithData:(NSData *)jsonData;
- (id)objectWithData:(NSData *)jsonData error:(NSError **)error;
- (id)mutableObjectWithData:(NSData *)jsonData;
- (id)mutableObjectWithData:(NSData *)jsonData error:(NSError **)error;

NSString 接口

- (id)objectFromJSONString;
- (id)objectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
- (id)objectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error;
- (id)mutableObjectFromJSONString;
- (id)mutableObjectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
- (id)mutableObjectFromJSONStringWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error;

NSData 接口

- (id)objectFromJSONData;
- (id)objectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
- (id)objectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error;
- (id)mutableObjectFromJSONData;
- (id)mutableObjectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags;
- (id)mutableObjectFromJSONDataWithParseOptions:(JKParseOptionFlags)parseOptionFlags error:(NSError **)error;

JKParseOptionFlags

解析选项描述
JKParseOptionNone这是没有指定其他解析选项标志时的默认值,也是在便捷方法没有提供显式指定要使用的解析选项的参数时的选项。与 JKParseOptionStrict 同义。
JKParseOptionStrictJSON 将根据 RFC 4627 规范严格解析。
JKParseOptionComments允许 JSON 中存在 C 风格的 ///* … */ 注释。这是 JSON 的一种相当常见的扩展,但包含 C 风格注释的 JSON 并不是严格遵循的 JSON。
JKParseOptionUnicodeNewlines允许 JSON 中出现 Unicode 推荐的新行字符 (?:\r\n|[\n\v\f\r\x85\p{Zl}\p{Zp}])。JSON 规范仅允许新行字符 \r\n,但此选项允许包含 Unicode 推荐新行字符的 JSON 被解析。包含这些额外新行字符的 JSON 不是严格遵循的 JSON。
JKParseOptionLooseUnicode通常情况下,解码器在遇到任何非规范Unicode时都会停止并出现错误。此选项允许JSON解析器在不报告错误的情况下解析有非规范Unicode的JSON。任何非规范Unicode都将被替换为\uFFFD,或如Unicode 6.0标准,第三章,3.9节所述的替换字符
JKParseOptionPermitTextAfterValidJSON通常情况下,跟随JSON之后的非空白字符会被解释为解析失败。此选项允许忽略任何尾随的非空白字符,并且不会导致解析错误。

序列化接口

序列化接口包括了一些NSString便捷方法,用于需要序列化单个NSString的情况。对于需要此功能的人来说,与必须在一个NSArray中包起来单个NSString并从序列化后的JSON结果中删除不需要的[]字符相比,这些NSString的添加要方便得多。当序列化单个NSString时,您可以通过使用includeQuotes:参数来控制序列化后的JSON结果是否带有引号。

示例 结果 参数
a "test"... "a \"test\"..." includeQuotes:YES
a "test"... a \"test\"... includeQuotes:NO

注意:不带includeQuotes:参数的NSString方法将像调用includeQuotes:YES一样执行。
注意:返回的NSData对象包含的字节是UTF8编码。

NSArray和NSDictionary接口

- (NSData *)JSONData;
- (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error;
- (NSString *)JSONString;
- (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions error:(NSError **)error;

NSString 接口

- (NSData *)JSONData;
- (NSData *)JSONDataWithOptions:(JKSerializeOptionFlags)serializeOptions includeQuotes:(BOOL)includeQuotes error:(NSError **)error;
- (NSString *)JSONString;
- (NSString *)JSONStringWithOptions:(JKSerializeOptionFlags)serializeOptions includeQuotes:(BOOL)includeQuotes error:(NSError **)error;

JKSerializeOptionFlags

序列化选项描述
JKSerializeOptionNone这是如果没有指定其他序列化选项标志时的默认选项,也是便捷方法在没有提供明确指定使用序列化选项的参数时使用的选项。
JKSerializeOptionPretty通常情况下,序列化后的JSON不包含任何不必要的空白字符。虽然这种形式最为紧凑,但缺乏任何空白字符意味着这种格式只有另一个JSON解析器才能喜欢。启用此选项会导致JSONKit添加额外的空白字符,使得阅读更为方便。除了额外的空白字符之外,序列化后的JSON与未启用此选项时将生成的JSON相同。
JKSerializeOptionEscapeUnicode当JSONKit在NSString对象中遇到Unicode字符时,默认行为是将这些Unicode字符编码为UTF8。此选项会导致JSONKit将这些字符编码为\uXXXX。例如,
["w∈L⟺y(∣y∣≤∣w∣)"]
变为
["w\u2208L\u27fa\u2203y(\u2223y\u2223\u2264\u2223w\u2223)"]
JKSerializeOptionEscapeForwardSlashes根据《JSON规范》(JSON specification),斜杠(/U+002F)字符可以反斜杠转义(即\/),但是这不是必填项。JSONKit的默认行为是转义斜杠字符。不幸的是,发现一些实际实现的ASP.NET日期格式要求日期必须严格编码为\/Date(...)\/,而实现这一点唯一的方法是通过使用JKSerializeOptionEscapeForwardSlashes。有关更多信息,请参阅github issue #21