Amazon SDK for PHP 版本 3 中的 JMESPath 表达式 - Amazon SDK for PHP
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

Amazon SDK for PHP 版本 3 中的 JMESPath 表达式

JMESPath 支持您以声明方式指定如何从 JSON 文档中提取元素。Amazon SDK for PHP 依赖 jmespath.php 来支持一些高级抽象,比如 Amazon SDK for PHP 版本 3 中的 Paginator 以及 Amazon SDK for PHP 版本 3 中的 Waiter,还对 Aws\ResultInterfaceAws\ResultPaginator 公开 JMESPath 搜索。

您可以在浏览器中通过在线 JMESPath 示例试用 JMESPath。您可以通过JMESPath 规范进一步了解这种语言,包括可用的表达式和功能。

Amazon CLI 支持 JMESPath。针对 CLI 输出编写的表达式与针对 Amazon SDK for PHP 编写的表达式完全兼容。

从结果中提取数据

Aws\ResultInterface 接口的 search($expression) 方法可根据 JMESPath 表达式从结果模型中提取数据。使用 JMESPath 表达式从结果对象中查询数据,有助于删除样板文件条件代码,并且更精确地表达提取出的数据。

为演示其工作方式,我们来看下面的默认 JSON 输出,它描述了连接到不同 Amazon EC2 实例的两个 Amazon Elastic Block Store (Amazon EBS) 卷。

$result = $ec2Client->describeVolumes(); // Output the result data as JSON (just so we can clearly visualize it) echo json_encode($result->toArray(), JSON_PRETTY_PRINT);
{ "Volumes": [ { "AvailabilityZone": "us-west-2a", "Attachments": [ { "AttachTime": "2013-09-17T00:55:03.000Z", "InstanceId": "i-a071c394", "VolumeId": "vol-e11a5288", "State": "attached", "DeleteOnTermination": true, "Device": "/dev/sda1" } ], "VolumeType": "standard", "VolumeId": "vol-e11a5288", "State": "in-use", "SnapshotId": "snap-f23ec1c8", "CreateTime": "2013-09-17T00:55:03.000Z", "Size": 30 }, { "AvailabilityZone": "us-west-2a", "Attachments": [ { "AttachTime": "2013-09-18T20:26:16.000Z", "InstanceId": "i-4b41a37c", "VolumeId": "vol-2e410a47", "State": "attached", "DeleteOnTermination": true, "Device": "/dev/sda1" } ], "VolumeType": "standard", "VolumeId": "vol-2e410a47", "State": "in-use", "SnapshotId": "snap-708e8348", "CreateTime": "2013-09-18T20:26:15.000Z", "Size": 8 } ], "@metadata": { "statusCode": 200, "effectiveUri": "https:\/\/ec2.us-west-2.amazonaws.com", "headers": { "content-type": "text\/xml;charset=UTF-8", "transfer-encoding": "chunked", "vary": "Accept-Encoding", "date": "Wed, 06 May 2015 18:01:14 GMT", "server": "AmazonEC2" } } }

首先,我们可以利用以下命令,只从“卷”列表中检索第一个卷。

$firstVolume = $result->search('Volumes[0]');

现在,我们使用 wildcard-index 表达式 [*] 迭代整个列表,提取三个元素并重命名:将 VolumeId 重命名为 ID,将 AvailabilityZone 重命名为 AZ,并将 Size 保留为 Size。我们可以将 multi-hash 表达式置于 wildcard-index 表达式之后,提取并重命名这些元素。

$data = $result->search('Volumes[*].{ID: VolumeId, AZ: AvailabilityZone, Size: Size}');

这样我们就有了如下的 PHP 数据:

array(2) { [0] => array(3) { 'AZ' => string(10) "us-west-2a" 'ID' => string(12) "vol-e11a5288" 'Size' => int(30) } [1] => array(3) { 'AZ' => string(10) "us-west-2a" 'ID' => string(12) "vol-2e410a47" 'Size' => int(8) } }

multi-hash 表示法中,您还可以使用串联的键(例如 key1.key2[0].key3)提取深度嵌套在结构中的元素。以下示例利用 Attachments[0].InstanceId 键演示此功能,别名指定为简单的 InstanceId。(在大多数情况下,JMESPath 表达式会忽略空格。)

$expr = 'Volumes[*].{ID: VolumeId, InstanceId: Attachments[0].InstanceId, AZ: AvailabilityZone, Size: Size}'; $data = $result->search($expr); var_dump($data);

上一表达式会输出以下数据:

array(2) { [0] => array(4) { 'ID' => string(12) "vol-e11a5288" 'InstanceId' => string(10) "i-a071c394" 'AZ' => string(10) "us-west-2a" 'Size' => int(30) } [1] => array(4) { 'ID' => string(12) "vol-2e410a47" 'InstanceId' => string(10) "i-4b41a37c" 'AZ' => string(10) "us-west-2a" 'Size' => int(8) } }

您还可以利用 multi-list 表达式筛选多个元素:[key1, key2]。此表达式会将每个对象筛选出的所有属性放入单个排序列表中,不考虑类型。

$expr = 'Volumes[*].[VolumeId, Attachments[0].InstanceId, AvailabilityZone, Size]'; $data = $result->search($expr); var_dump($data);

运行上一搜索会生成以下数据:

array(2) { [0] => array(4) { [0] => string(12) "vol-e11a5288" [1] => string(10) "i-a071c394" [2] => string(10) "us-west-2a" [3] => int(30) } [1] => array(4) { [0] => string(12) "vol-2e410a47" [1] => string(10) "i-4b41a37c" [2] => string(10) "us-west-2a" [3] => int(8) } }

使用 filter 表达式按特定字段的值筛选结果。以下示例查询仅输出 us-west-2a 可用区中的卷。

$data = $result->search("Volumes[?AvailabilityZone ## 'us-west-2a']");

JMESPath 也支持函数表达式。假设您希望运行的查询与上述查询相同,但要检索以“us-”开头的 Amazon 区域中的所有卷。以下表达式使用 starts_with 函数,传递 us- 文本字符串。然后将此函数的结果与 JSON 文本值 true 进行比较,仅传递通过筛选投影返回 true 的筛选断言结果。

$data = $result->search('Volumes[?starts_with(AvailabilityZone, 'us-') ## `true`]');

从分页工具提取数据

正如您可以通过 Amazon SDK for PHP 版本 3 中的 Paginator 指南了解到的,Aws\ResultPaginator 对象可用于从可分页的 API 操作生成结果。您可以利用Amazon SDK for PHP提取并迭代使用 Aws\ResultPaginator 对象筛选出的数据,也就是针对迭代器实施扁平化映射,在迭代器中 JMESPath 表达式的结果是 Map 函数。

假设您希望创建 iterator,以仅从存储桶生成大于 1 MB 的对象。要做到这一点,应首先创建 ListObjects 分页工具,然后为该分页工具应用 search() 函数,针对分页数据创建扁平化映射的迭代器。

$result = $s3Client->getPaginator('ListObjects', ['Bucket' => 't1234']); $filtered = $result->search('Contents[?Size > `1048576`]'); // The result yielded as $data will be each individual match from // Contents in which the Size attribute is > 1048576 foreach ($filtered as $data) { var_dump($data); }