Rambler.iOS #8 - Как не стать жертвой бэкендеров
-
Upload
rambler-ios -
Category
Technology
-
view
324 -
download
4
Transcript of Rambler.iOS #8 - Как не стать жертвой бэкендеров
Как не стать жертвой бекендеров
Ирина Дягилева RAMBLER&Co
Нужна ли валидация ответа сервера?
2
3
Crash-free
4
5
Нужен контракт между клиентом и сервером
и его валидация
6
План
• Валидация ответа сервера
• JSON-схема
• Библиотеки
• Время валидации
• Полезные инструменты
7
LiveJournal@implementation RegistrationResponseValidator
- (NSError *)validateServerResponse:(id)response {
NSError *resultError = nil;
return resultError; }
@end
if (![super validateResponseIsErrorClass:response error:&resultError]) { return resultError; } if(![super validateResponseIsDictionaryClass:response error:&resultError]) { return resultError; }
if (response[@"access_token"] == nil || response[@"displayName"] == nil || response[@"id"] == nil) { resultError = ...; // создание ошибки валидации }
8
Афиша- (NSError *)validateResponseObject:(id)responseObject mapping:(EKManagedObjectMapping *)mapping {
return nil; }
NSError *validationError = [self validateResponseObject:responseObject]; if (validationError) { return [self validationError]; }
NSArray *primaryKeys = mapping.rca_primaryKeys; if (primaryKeys) { for (NSString *primaryKey in primaryKeys) { EKPropertyMapping *propertyMapping = [self propertyMappingForPrimaryKey:primaryKey mapping:mapping]; if (!responseObject[propertyMapping.keyPath]) { return [self validationError]; } } }
9
JSON Schemahttp://json-schema.org/
это JSON
набор инструкций для описания структуры JSON документов
10
Типы объектов JSON JSON Schemastring string
number number/integerobject objectarray arraytrue truefalse falsenull null
11
Примеры json-схем
{ "type": "boolean" }
true
12
false
"true"
30
Строковые типы{ "type": "string", "minLength": 7, "maxLength": 9 }
13
"12345678"
"#FF0000"
"12345"
true
{ "type": "string", "pattern": "^#[0-9a-fA-F]{6}$" }
Строковые типы
14
"#FFFFFf22"
"#3C2FCB"
"FFFFFf22"
"#3C2FCB00"
14
Строковые типы{ "type": "string", "format": "email" }
"email", "date-time", "hostname", "ipv4", "ipv6", "uri"
15
"[email protected]" "i.dyagileva"
Числовые типы{ "type": "integer", "minimum": 200, "maximum": 500, "exclusiveMinimum": true, "multipleOf": 5 }
16
205
500
200
104
Перечисления{ "type": "string", "enum": [ "red", "green", "blue" ] }
17
"red"
"blue"
"pink"
"#FFFFFF"
Массивы{ "type": "array", "items": { "type": ["string", "integer"] }, "minItems": 2, "maxItems": 3, "uniqueItems": true }
18
["a", 2]
[4, 5, 6]
[1, 2, 1]
["a", "b", "c", "d"]
Объекты{ "type": "object", "properties": { "articleID": { "type": "string" }, "title": { "type": "string" }, "subtitle": { "type": "string" } },
"required": ["articleID","title"], }
{ "articleID": "1", "title": "Заголовок", "subtitle": "Подзаголовок"
}
{ "articleID": "1", "subtitle": "Подзаголовок"}
19
Объекты{ "type": "object", "properties": { "articleID": { "type": "string" }, "title": { "type": "string" }, "subtitle": { "type": "string" } },
"required": ["articleID","title"], "additionalProperties": false }
{ "articleID": "1", "title": "Заголовок", "subtitle": "Подзаголовок"
}
{ "articleID": "1", "title": "Заголовок", "subtitle": "Подзаголовок", "description": "Описание"
}
20
Определения{ "type": "object", "properties": { "backgroundColor": { "$ref": "#/definitions/color" }, "foregroundColor": { "$ref": "#/definitions/color" } }, "definitions": { "color": { "type": "string", "pattern": "^#[0-9a-fA-F]{6}$" } } }
21
{ "backgroundColor": "#FFFFFF", "foregroundColor": "#FF0000"}
{ "backgroundColor": "FFFFFF", "foregroundColor": "#FF"}
Композиция{ "type": "array", "items": { "allOf": [ { "type": "integer", "minimum": 0
}, { "type": "integer", "multipleOf": 5
} ] } }
22
[5, 15]
[-4, 5]
[0, 0]
[1, 8]
Композиция{ "type": "array", "items": { "anyOf": [ { "type": "integer", "minimum": 0
}, { "type": "integer", "multipleOf": 5
} ] } }
23
[-5, 5]
[-4, 5]
[1, 8]
[1, "8"]
Композиция{ "type": "array", "items": { "oneOf": [ { "type": "integer", "minimum": 0
}, { "type": "integer", "multipleOf": 5
} ] } }
24
[1, 8]
[0, 0]
[1, -5]
[1, -4]
Композиция{ "type": "object", "properties": { "likeValue": { "type": "boolean" }, "place": { "type": "string" }, "event": { "type": "string" } }, "required": ["likeValue"] , "oneOf": [ { "required": ["place"] }, { "required": ["event"] } ] }
25
{ "likeValue": true, "event": "event",}
{ "likeValue": true, "event": "event", "place": "place"}
{ "likeValue": true }
Отрицание{ "type": "array", "items": { "not": { "anyOf": [ { "type": "integer", "minimum": 0 }, { "type": "integer", "multipleOf": 5 } ] } } }
26
[-1, -4]
[-1, -5]
[-8, -8]
[1, -4]
Объявление схемы
{ "$schema": "http://json-schema.org/draft-04/schema#",
}
27
"id": "http://domain.com/schemas/myschema.json"
{
}
"$schema": "http://json-schema.org/draft-04/schema#",
Объявление схемы
28
"id": "http://domain.com/schemas/myschema.json"
Валидатор
29
/** Протокол валидатора ответа сервера */ @protocol ROSResponseValidator <NSObject>
- (BOOL)validateResponse:(id)response withSchema:(NSDictionary *)schema error:(NSError **)error;
@end
30
/** Протокол поставщика json-схем */ @protocol ROSJSONSchemaProvider <NSObject>
- (NSDictionary *)sectionsSchema;
- (NSDictionary *)articleSchema;
@end
31
Библиотеки ObjC
• KiteJSONValidator 39
• JSONTools 41
• JSONSchemaValidation 14
32
Время валидации
34
3 %12 %
8 %
77 %СкачиваниеВалидацияМаппингПонсомизация
Запрос списка секцийОПЕРАЦИЯ ВРЕМЯ (С)Скачивание 0,2012Валидация 0,0215Маппинг 0,0323Понсомизация 0,0069
Время валидации
35
4 %11 %
30 % 55 %СкачиваниеВалидацияМаппингПонсомизация
Запрос тела статьиОПЕРАЦИЯ ВРЕМЯ (С)Скачивание 0,1040Валидация 0,0560Маппинг 0,0217Понсомизация 0,0071
Полезные ссылки и инструменты
Итоги
• Предотвращение ошибок и падений приложения
• Документирование структур данных, стандартизация
• Помощь при тестировании
• Генерация моков
41