TypedJSON 1.2.0

TypedJSON 1.2.0

维护者: tonyzp.



TypedJSON 1.2.0

  • tp

TypedJSON

CI Status Version License Platform

处理 Objective-C JSON 字典的方式很丑。

Objective-C 是一种运行时,弱类型语言。Objective-C 中的 NSDictionary 类不是一个类型安全的对象。

假设我们有一个 json 字典

NSDictionary *json = @{ @"username": @"tp", @"password": @"123456", @"scores": @{ @"programming": @70, @"language": @80 }, @"tels": @[ @"1367890876", @"02884435261" ] };

我们可以这样访问字典:

NSString *username = json[@"username"];

if (!username || ![username isKindOfClass:NSString.class] || username.length == 0) {
    return;
}

// Do something with username string

或者:

NSDictionary *scores = json[@"scores"];

if (!scores || ![scores isKindOfClass:NSDictionary.class] || scores.count == 0) {
    return;
}

NSNumber *score = scores[@"programming"];

if (!score || ![score isKindOfClass:NSNumber.class]) {
    return;
}

// Do something with programming score number

这里的问题在于,我们做了很多类型与值的检查以确保类型安全性,这使得我们的代码很丑

这种方法更好

使用 TypedJSON,我们使用链式操作符以语义化的方式解决这个问题。这试图确保代码的优雅性和可读性。

NSString *username = json.tj.string(@"username").without.empty.value;

if (!username) {
    return;
}

// Do something with username string

NSNumber *score = json.tj.dictionary(@"scores").number(@"programming").value;

if (!score) {
    return;
}

// Do something with programming score number

更多示例

此示例中的 json 数据

{
    "username": "tp",
    "password": "123456",
    "scores": {
        "programming": 70,
        "language": 80
    },
    "tels": [
        "+8613612345678",
        "028-84555555"
    ]
}

如何使用 TypedJSON 访问此 json 字典

NSDictionary *json = [self loadJSON];
    
// Get username from json exclued empty string value '', return 'anonymous' while nil.
NSString *username = json.tj.string(@"username").without.empty.defaults(@"anonymous").value;
    
// Get programming score number in scores dictionary from json.
NSNumber *programmingScore = json.tj.dictionary(@"scores").number(@"programming").value;
    
// Get politics score number in scores dictionary from json, return 0 while politics do not exists.
NSNumber *politicsScore = json.tj.dictionary(@"scores").number(@"politics").with.defaults(@0).value;
    
NSLog(@"The programming score of %@ is %@, and politics %@.", username, programmingScore, politicsScore);

安装

TypedJSON可以通过CocoaPods进行安装。要安装它,只需将以下行添加到您的Podfile

pod 'TypedJSON'

然后运行pod install以进行集成。

用法

要导入TypedJSON,您只需

#import <TypedJSON/TypedJSON.h>

在字典中以类型安全的方式读取值

使用指定键在字典中读取字符串

json.tj.string(@"foo").value;

如果值不是NSString类型,则值可能是nil

使用指定键在字典中读取数字

json.tj.number(@"foo").value;

如果值不是NSNumber类型,则值可能是nil

使用指定键在字典中读取数组

json.tj.array(@"foo").value;

如果值不是NSArray类型,则值可能是nil

使用指定键在字典中读取字典

json.tj.dictionary(@"foo").value;

如果值不是NSDictionary类型,则值可能是nil

确保不为空

有时我们在字典中会得到空值,例如

  • 空字符串:""
  • 空数组:@[]
  • 空字典:@{}

使用- empty操作符来忽略它们

json.tj.string(@"foo").without.empty.value;

如果"foo"的值为一个空字符串"",则返回nil

json.tj.array(@"foo").without.empty.value;

如果"foo"的值为一个空数组@[],则返回nil

json.tj.dictionary(@"foo").without.empty.value;

如果"foo"的值为一个空字典@{},则返回nil

在获取nil值时提供默认值

假设我们得到了链中的nil值,我们需要提供一个默认值

json.tj.string(@"foo").with.defaults(@"bar").value;

可以省略- with操作符,这只是为了确保语句的语义。

《- any》运算符

此运算符仅通过指定键获取值,不进行类型检查。

json.tj.any(@"foo").value;

返回值是 id 类型。

或者,您可以使用 Valuable 扩展来执行类型检查。

json.tj.any(@"foo").stringValue;

- stringValue 确保返回值匹配 NSString 类型,如果不匹配则返回 nil

以链式方式访问值

假设值被包装在内层字典中。

{
    "foo": {
        "bar": {
            "greeting": "Hello ~"
        }
    }
}

我们可以以链式方式访问 greeting

json.tj.dictionary(@"foo").dictionary(@"bar").string(@"greeting").value;

《- find》运算符

在上面的示例中,我们通过运算符链访问 greeting,使用 - find 运算符可以修改代码。

json.tj.find(@"greeting").value;

- find 运算符递归枚举字典以获取匹配特定键的值,但不执行类型检查。为了确保类型安全,我们可以使用 Valuable 扩展方法 - stringValue

json.tj.find(@"greeting").stringValue;

《- as》运算符

此运算符类似于 Valuable 扩展方法。它确保值匹配指定的类类型。通常我们在运算符链中使用此运算符在 - find- any 运算符之后。

json.tj.find(@"greeting").as(NSString.class).value;

确保 - find 运算符的 @"greeting" 结果值匹配 NSString 类。

等同于

json.tj.find(@"greeting").stringValue;

错误情况

如果 json 对象为 nil 或不是 NSDictionary 的子类,直接使用 .tj 可能会导致程序崩溃。因此,我们在使用 tj 访问之前,应该对 json 对象进行 可空性 & 类型检查。或者,我们可以使用 TJ(json) 宏来为您执行此操作。

// The `json` object could be `nil`, or it's class is NOT a kind of NSDicionary.
NSString *username = TJ(json).string(@"username").without.empty.defaults(@"anonymous").value;

作者

tp, [email protected]

许可证

TypedJSON 在 MIT 许可证下可用。有关更多信息,请参阅 LICENSE 文件。