浅谈后置处理器之JSON提取器
JMeter 的 JSON 提取器(JSON Extractor)是一个强大的后置处理器,它允许用户从HTTP响应、数据库查询或其他类型的响应中提取JSON数据,并将这些数据存储为变量,以便在后续的请求中重用。这对于需要动态处理基于JSON格式API测试的场景尤为有用。以下是对JSON提取器的详细说明和使用教程。
使用场景
● 参数化请求:从一个API响应中提取token或其他标识符,用于后续请求的认证或数据关联。
● 数据驱动测试:提取JSON数组中的多个值,用于遍历测试不同的数据集。
● 验证响应内容:检查特定的JSON字段是否存在或其值是否符合预期。
配置步骤
添加JSON提取器
- 在你的JMeter测试计划中,选择一个采样器(如HTTP请求)。
- 右键点击该采样器,选择“添加” > “后置处理器” > “JSON 提取器”。
配置参数
JSON 提取器提供了多个配置选项,以下是关键参数的解释:
● 名称: 给这个后置处理器一个描述性的名称,便于识别。
● Names of created variables:变量名称
● JSON Path expressions: 输入JSON路径表达式,用于定位你想要提取的数据。例如$.username会提取根对象下的username字段。
● Match No. (0 for Random):
○ 0: 随机选择一个匹配项。
○ n: 提取第n个匹配项(n为正整数)。
○ -1: 提取所有匹配项,并以变量数组形式存储。
● Compute concatenation var(suffix_ALL):匹配到的所有数值并保存,默认为空即可
● Default Values: 如果没有找到匹配的JSON路径,可以设置一个默认值。
变量命名与引用
● 变量名: 为提取的数据指定一个变量名。如果Match No.设置为-1,则应使用数组形式的变量名,如users_,这样每个匹配项将会被命名为users_1、users_2等。
示例
假设你有一个API响应如下:
{
"status": "success",
"data": {
"userId": 12345,
"username": "exampleUser"
}
}
要提取username值,你可以配置JSON Extractor如下:
● JSON Path expressions: $.data.username
● Names of created variables: userNameVar
● Match No.: 1
之后,在JMeter中任何地方可以通过${userNameVar}引用提取到的用户名。
应用实例
首先我们使用SpingBoot编写部分测试接口代码
@PostMapping(value = "/login",produces = "application/json;charset=UTF-8")
public String authenticate(@RequestBody JSONObject request) {
String validUsername = "admin";
String validPassword = "password";
String response = "{\"total\":2,\"data\":[{\"id\":123,\"name\":\"John Doe\",\"email\":\"johndoe@example.com\",\"phone\":\"123-456-7890\",\"address\":{\"street\":\"123 Main St\",\"city\":\"New York\",\"state\":\"NY\",\"zip\":\"10001\"},\"interests\":[\"sports\",\"music\",\"travel\"]},{\"id\":456,\"name\":\"Jane Smith\",\"email\":\"janesmith@example.com\",\"phone\":\"987-654-3210\",\"address\":{\"street\":\"456 Elm St\",\"city\":\"Los Angeles\",\"state\":\"CA\",\"zip\":\"90001\"},\"interests\":[\"reading\",\"cooking\",\"hiking\"]}]}";
if (request.getString("username").equals(validUsername) && request.getString("password").equals(validPassword)) {
return response;
} else {
return response;
}
}
我们编写如下测试脚本
线现程组:保持默认
HTTP信息头管理器:名称content-type,值为application/json;charset=UTF-8
HTTP请求:协议http,服务器名称或IP为127.0.0.1,端口设置为8091,方法为post,路径/login,内容编码为utf-8,消息体数据设置如下
{
"username": "admin",
"password": "password"
}
运行脚本,查看结果树,在HTTP请求的响应数据中Response Body查看结果如下(已经美化JSON格式):
{
"total": 2,
"data": [
{
"address": {
"zip": "10001",
"city": "New York",
"street": "123 Main St",
"state": "NY"
},
"phone": "123-456-7890",
"name": "John Doe",
"id": 123,
"interests": [
"sports",
"music",
"travel"
],
"email": "johndoe@example.com"
},
{
"address": {
"zip": "90001",
"city": "Los Angeles",
"street": "456 Elm St",
"state": "CA"
},
"phone": "987-654-3210",
"name": "Jane Smith",
"id": 456,
"interests": [
"reading",
"cooking",
"hiking"
],
"email": "janesmith@example.com"
}
]
}
情况1:返回值中提取total数据
JSON提取器中Names of created variables设置为var,JSON Path expressions设置为total或者$.total,两种效果一致,Match No. (0 for Random)设置为-1,Default Values设置为NotFound。
运行脚本,查看结果树中响应数据的Response Body
var_1=2
var_matchNr=1
情况2:返回值中提取address数据
JSON提取器中Names of created variables设置为var,JSON Path expressions设置为data[*].address或者$.data[*].address,两种效果一致,Match No. (0 for Random)设置为-1,Default Values设置为NotFound。
运行脚本,查看结果树中响应数据的Response Body
var_1={“zip”:“10001”,“state”:“NY”,“city”:“New York”,“street”:“123 Main St”}
var_2={“zip”:“90001”,“state”:“CA”,“city”:“Los Angeles”,“street”:“456 Elm St”}
var_matchNr=2
情况3:返回值中提取address数只需要上述情况2中var_1的数据
JSON提取器中Names of created variables设置为var,JSON Path expressions设置为data[0].address或者$.data[0].address,两种效果一致,Match No. (0 for Random)设置为-1,Default Values设置为NotFound。
运行脚本,查看结果树中响应数据的Response Body
var_1={“zip”:“10001”,“state”:“NY”,“city”:“New York”,“street”:“123 Main St”}
var_matchNr=1
情况4:返回值中提取interests的数据
JSON提取器中Names of created variables设置为var,JSON Path expressions设置为data[*].interests[*]或者$.data[*].interests[*],两种效果一致,Match No. (0 for Random)设置为-1,Default Values设置为NotFound。
运行脚本,查看结果树中响应数据的Response Body
var_1=sports
var_2=music
var_3=travel
var_4=reading
var_5=cooking
var_6=hiking
var_matchNr=6
情况5:返回值中提取interests的数据第一行的数据,即Sports和Reading
JSON提取器中Names of created variables设置为var,JSON Path expressions设置为data[*].interests[0]或者$.data[*].interests[0],两种效果一致,Match No. (0 for Random)设置为-1,Default Values设置为NotFound。
运行脚本,查看结果树中响应数据的Response Body
var_1=sports
var_2=reading
var_matchNr=2
情况6:勾选Compute concatenation var(suffix_ALL)
初勾选Compute concatenation var(suffix_ALL),其他设置跟情况5一直。
运行脚本,查看结果树中响应数据的Response Body
var_1=sports
var_2=reading
var_ALL=sports,reading
var_matchNr=2
注意事项
● 确保JSON路径表达式正确无误。
● 当提取多个值时,合理设置Match No.和变量名格式,避免数据混乱。
● 对于复杂的JSON结构,深入理解JSONPath语法将大大提高提取效率。
通过以上步骤和注意事项,你应该能够有效地使用JMeter的JSON提取器来处理和利用JSON响应数据,进而构建更加动态和强大的性能测试脚本。