亚马逊AWS官方博客

使用 AWS Lambda Powertools进行定制化数据验证

背景故事

任何应用最本质的东西其实都是数据,用户使用产品的过程,就是在和产品进行数据交换的过程。比如在电商平台中,产品的介绍信息,描述信息,参数信息,时时刻刻都在与终端客户进行交互,因此作为应用程序,数据的验证就变得至关重要。

当您的程序需要从上游程序数据源读取数据时,很有可能存在数据格式及内容的不合规范,这一数据问题严重威胁着后续程序的鲁棒性。另一方面,如果我们自己完全去手写验证数据的代码,本身开发成本比较高,又由于这部分代码的业务逻辑性强,也不易于后期的迭代和维护。

为了解决以上这些问题,我们引入了带有基于JSON Schema的验证模块的开源库,AWS Lambda Powertools。JSON Schema 是对 JSON 数据进行数据结构描述的一个协议,按照协议的规定,我们既可以对 JSON 数据的结构进行描述,也可以通过上述描述内容验证特定的 JSON 数据。而 Lambda Powertools 在 Python 版本就集成了 JSON Schema 验证的功能。在这篇文章中,我们将介绍如何使用 Powertools 在无服务器架构的 Amazon Lambda 中对JSON进行数据验证。

 

关于AWS Lambda Powertools validation

Lambda Powertools是一个AWS推出的开源框架库,它可以帮助开发人员大幅提升工作效率,减少重复劳动,从而提高生产力。 它目前支持使用 Python 3.6 及以上版本编写的 AWS Lambda 函数。 它内嵌的 validation 功能可以让您通过编写 JSON Schema 对数据进行定制化校验,基于定制化的 JSON Schema ,它主要具有以下几项功能:

  1. 调用函数对某一字典直接进行验证
  2. 对传入事件(incoming event)和响应进行验证
  3. 支持使用JMESPath在数据验证之前对事件内容进行提取
  4. 支持使用预置包封(Built-in envelopes)对热门事件(popular event)的负载进行提取

在本篇文章中我们将着重介绍JSON Schema文件的编写规则和调用函数对数据进行校验的方法。

 

配置与安装

AWS Powertools包托管于PyPi,因此我们可以使用 pip 直接进行安装(当你使用一些功能时,requests ,  boto3 也有可能需要被安装)。除此之外,我们还建议你将 AWS Lambda Powertools 添加到你的项目依赖文件中,我们这里以 pip freeze 到 requirements.txt 为例:

$ pip install aws_lambda_powertools
$ pip freeze | grep aws_lambda_powertools >> requirements.txt

JSON Schema验证示例

假如有如下场景,我们的数据源是下方的JSON文件(文件名country.json),我们希望该文件为一个包含的所有对象至少拥有“country”属性的列表。

内容如下:

[{
    "country": "JP",
    "ship_from": true,
    "ship_to": false
}, 
{
  "country": "CN",
  "ship_from": true,
  "display_name": "China",
  "ship_to": false
},
{
  "country": "",
  "ship_from": true,
  "display_name": "United States",
  "ship_to": false
}]

为了完成上述的需求,我们可以编写对应的JSON Schema,并将其储存为Python字典的格式,我们可以单独建立一个新文件储存该字典常量,如country_template.py,内容如下:

# We organize Json Schema in python's dictionary form.
# Json Schema use "false", but python use False.
# Json Schema don't support any comment.
COUNTRY_TEMPLATE = {
    "required": [
        "country",  # Partition Key must exist
    ],
    "type": "object",  # Correspond to dict in python
    "properties": {
        "country": {
            "minLength": 1,  # Because it's the Partition Key
            "examples": [
                "US"
            ],
            "type": "string"
        },
        "ship_from": {
            "type": "boolean"
        },
        "display_name": {
            "examples": [
                "United States"  # You can write a example for people to understand
            ],
            "type": "string"
        },
        "ship_to": {
            "type": "boolean"
        }
    },
    # We don't tolerate any property excpet those above.
    "additionalProperties": False
}

对于上方的来自数据源的文件和JSON Schema验证模版,我们可以编写如下的Python代码,我们不妨将其储存为validate.py:

from aws_lambda_powertools.utilities.validation import validate, SchemaValidationError
from country_template import COUNTRY_TEMPLATE
import json

json_countries = json.load(open('country.json')) 

for country in json_countries:
    try:
        validate(event = country, schema = COUNTRY_TEMPLATE)
        print("No errors in data: " + country["country"])
    except SchemaValidationError as validation_error:
        print(validation_error)

上述的代码运行结果如下:

No errors in data: JP
No errors in data: CN
Failed schema validation. Error: data.country must be longer than or equal to 1 characters, Path: ['data', 'country'], Data:

当Python抛出 SchemaValidationError 时,我们可以使用 try-except 语句获取错误信息并进行解析,所有的错误类型可以在 PowerTools 集成的开源工具Fast JSON schema validator for Pythonfastjsonschema文件夹下的 draftXX.py 中找到。

 

Json Schema 验证进阶

由于AWS Powertools并没有在官方文档给出Json Schema的具体写法,我们在这里简单介绍一些Json Schema语法,读者也可以根据提示的关键字对语法进行进一步搜索。

1. String

功能 关键词
限定字符串长度 “minLength”, “maxLength”
正则匹配 “pattern”
枚举 “enum”

在下面的示例中我们验证了一个由大写字母构成,长度在1~99个字符之间,且必须在“CN”, “US”, “JP”的中的字符串:

{
    "type": "string",
    "minLength": 1,
    "maxLength": 9999,
    "pattern": "[A-Z]+",
    "enum": ["CN", "US", "JP"],
    "examples": [
        "US"
    ]
}

2. Integer

功能 关键词
限定数字大小 “minimum”, “maximum”, “exclusiveMinimum”, “exclusiveMaximum”
倍数 “multipleOf”

在下面的示例中我们验证了一个必须大于1,小于等于100而且为3的倍数的整数:

{
   "type": "integer",
   "exclusiveMinimum": 1,
   "maximum": 100,
   "multipleOf": 3
}

3. Object

功能 关键词
键名 “properties”, “patternProperties”
额外的键 “additionalProperties”
必须有的键 “required”
键的数量 “minProperties”, “maxProperties”

Object的例子可以参考JSON Schema验证示例部分。

此外,JSON Schema也支持数组类型的验证以及其他的一些引用功能,读者如果有需要可以参考JSON Schema手册。

 

辅助工具

JSON Schema也可以使用开源工具直接从Json文件中自动推导生成(JSON Schema Tool),如下图所示:

在此之后,我们还需要对生成的框架进行精简和调整以适应其他JSON数据(可以参考验证进阶部分的内容进行调整)。与此同时,我们也可以找到很多JSON Schema验证的开源工具,它们可以方便我们对JSON Schema进行测试和验证(JSON Schema Validator)。

 

总结

今天是移动互联网的时代,也是数据信息的时代。无论是在电商运营中,还是在社交媒体中,数据都扮演着举足轻重的角色。在系统之间进行数据交互的场景下,应用程序的鲁棒性(Robust)十分依赖于数据本身的健壮性(Fitness)和一致的(Consistency)。因此,对于数据的接收方来说,对数据的格式,内容的验证过程显得至关重要。

通常我们可以自己编写代码在进程使用前对数据进行进行验证,但是这样做往往会存在代码复杂不易修改和验证覆盖度较低的问题。相比于传统的验证方式,AWS Lambda Powertools提供了一种更清晰简洁的校验方式。依托于JSON Schema强大的拓展性,它理论上几乎可以实现对任何内容的json文件的验证。而丰富的JSON Schema工具无疑进一步提高了生产效率,希望本文能够给您提供一些帮助,更好的时间数据的验证。通过对数据进行细致地校验,可以显著降低不符合系统规范的数据进入系统,大幅度降低系统不稳定甚至崩溃的风险。

 

本篇作者

张晓功

AWS云原生应用架构师,负责基于AWS的云计算方案架构的咨询和设计,同时致力于AWS云服务在国内的应用和推广。精通微服务架构设计、治理、容器编排、监控熔断等性能和可靠性等具体功能落地。具有丰富的互联网产品开发、大规模并行计算、性能优化等经验。

王钧睿

云原生应用实习生,负责基于AWS的云计算方案架构的设计和实施开发。对高级算法和计算机系统底层架构以及编译过程具有研究和热情,致力于用高效稳定的程序为客户解决实际问题。