【问题标题】:Pulling multiple values from JSON response using RegEx Extractor使用 RegEx Extractor 从 JSON 响应中提取多个值
【发布时间】:2011-11-14 17:55:22
【问题描述】:

我正在测试一个返回 JSON 响应的 Web 服务,我想从响应中提取多个值。典型的响应将在列表中包含多个值。例如:

{
"name":"@favorites",
"description":"Collection of my favorite places",
"list_id":4894636,
}

响应将包含许多与上述示例类似的部分。

我想在 Jmeter 中做的是检查 JSON 响应,并以一种我可以将返回的名称和描述作为一个条目进行迭代的方式提取上面概述的每个部分。

到目前为止,我能够做的是使用模板 $1$ 使用正则表达式提取器 ("name":"(.+?)") 返回名称值。我想同时提取名称和描述,但似乎无法正常工作。我尝试使用带有 $1$$2$ 模板的正则表达式 "name":"(.+?)","description":"(.+?)" 没有任何成功。

有谁知道在这个例子中我如何使用正则表达式提取多个值?

【问题讨论】:

标签: regex json jmeter


【解决方案1】:

您可以将(?s) 添加到正则表达式以避免换行。

例如:(?s)"name":"(.+?)","description":"(.+?)"

它适用于我的断言。

【讨论】:

    【解决方案2】:

    可能值得使用BeanShell scripting 来处理 JSON 响应。

    因此,如果您需要从响应(每个部分)中获取所有“名称/描述”对,您可以执行以下操作:
    1. 从循环中的响应中提取所有“名称/描述”对;
    2. 以方便的格式将提取的对保存在 csv 文件中;
    3. 稍后在代码中从 csv 文件中读取保存的对 - 在循环中使用 CSV Data Set Config,例如

    可以使用 BeanShell 脚本 (~ java) + 任何 json 处理库(例如 json-rpc-1.0)来实现 JSON 响应处理:
    - 在BeanShell SamplerBeanShell PostProcessor 中;
    - 当前默认提供所有必需的 beanshell 库 jmeter 交付;
    - 使用 json-processing 库将 jar 放入 JMETER_HOME/lib 文件夹。

    大致如下:

    1. 如果是 BeanShell 后处理器:

      线程组 . . . 您的 HTTP 请求 BeanShell PostProcessor // 作为子级添加 . . .
    2. 如果是 BeanShell 采样器:

      线程组 . . . 您的 HTTP 请求 BeanShell Sampler // 添加了单独的采样器 - 在你之后 . . .

    在这种情况下,使用哪一种没有区别。

    您可以将代码本身放入采样器主体(“脚本”字段)或存储在外部文件中,如下所示。

    采样器代码:

    import java.io.*;
    import java.util.*;
    import org.json.*;
    import org.apache.jmeter.samplers.SampleResult;
    
    ArrayList nodeRefs = new ArrayList();
    ArrayList fileNames = new ArrayList();
    
    String extractedList = "extracted.csv";
    StringBuilder contents = new StringBuilder();
    
    try
    {
        if (ctx.getPreviousResult().getResponseDataAsString().equals("")) {
            Failure = true;
            FailureMessage = "ERROR: Response is EMPTY.";
            throw new Exception("ERROR: Response is EMPTY.");
        } else {
            if ((ResponseCode != null) && (ResponseCode.equals("200") == true)) {
                SampleResult result = ctx.getPreviousResult();    
                JSONObject response = new JSONObject(result.getResponseDataAsString());
    
                FileOutputStream fos = new FileOutputStream(System.getProperty("user.dir") + File.separator + extractedList);
    
                if (response.has("items")) {
                    JSONArray items = response.getJSONArray("items");
    
                    if (items.length() != 0) {
                        for (int i = 0; i < items.length(); i++) {
                            String name = items.getJSONObject(i).getString("name");
                            String description = items.getJSONObject(i).getString("description");
                            int list_id = items.getJSONObject(i).getInt("list_id");
    
                            if (i != 0) {
                                contents.append("\n");
                            }
    
                            contents.append(name).append(",").append(description).append(",").append(list_id);
                            System.out.println("\t " + name + "\t\t" + description + "\t\t" + list_id);
                        }
                    }                                       
                }
    
                byte [] buffer = contents.toString().getBytes();    
    
                fos.write(buffer);
                fos.close();
            } else {
                Failure = true;
                FailureMessage = "Failed to extract from JSON response.";
            }
        }
    }
    catch (Exception ex) {
        IsSuccess = false;
        log.error(ex.getMessage());
        System.err.println(ex.getMessage());
    }
    catch (Throwable thex) {
        System.err.println(thex.getMessage());
    }
    

    还有一组关于此的链接:


    更新。 2017 年 8 月:

    目前 JMeter 有一组内置组件(从 3rd 方项目合并)来处理 JSON 而无需编写脚本:

    【讨论】:

      【解决方案3】:

      我假设 JMeter 使用基于 Java 的正则表达式...这可能意味着没有 named 捕获组。显然,Java7 now supports them,但这并不一定意味着 JMeter 会。对于如下所示的 JSON:

      {
      "name":"@favorites",
      "description":"Collection of my favorite places",
      "list_id":4894636,
      }
      
      {
      "name":"@AnotherThing",
      "description":"Something to fill space",
      "list_id":0048265,
      }
      
      {
      "name":"@SomethingElse",
      "description":"Something else as an example",
      "list_id":9283641,
      }
      

      ...这个表达式:

      \{\s*"name":"((?:\\"|[^"])*)",\s*"description":"((?:\\"|[^"])*)",(?:\\}|[^}])*}
      

      ...应该匹配3次,将“name”值捕获到第一个捕获组中,将“description”值捕获到第二个捕获组中,类似如下:

      1                 2
      ---------------   ---------------------------------------
      @favorites        Collection of my favorite places
      @AnotherThing     Something to fill space
      @SomethingElse    Something else as an example
      

      重要的是,这个表达式支持在值部分(甚至在标识符名称部分)中的引号转义,因此 Javascript 字符串 I said, "What is your name?"! 将存储在 JSON 中,并正确解析为 I said, \"What is your name?\"!

      【讨论】:

        【解决方案4】:

        使用 JMeter 的 Ubik Load Pack 插件,该插件已捐赠给 JMeter 核心,并且自 3.0 版起可作为 JSON Extractor 使用,您可以通过以下测试计划这样做:

        namesExtractor_ULP_JSON_PostProcessor 配置:

        descriptionExtractor_ULP_JSON_PostProcessor 配置:

        循环控制器循环结果:

        计数器配置:

        Debug Sampler 展示了如何在一次迭代中使用名称和描述:

        以下是您从以下 JSON 获得的结果:

         [{ "name":"@favorites", "description":"Collection of my favorite places", "list_id": 4894636 }, { "name":"@AnotherThing", "description":"Something to fill space", "list_id": 48265 }, { "name":"@SomethingElse", "description":"Something else as an example", "list_id":9283641 }]
        

        与 Beanshell 解决方案相比:

        • 这是更“标准的方法”

        • 它的性能比 Beanshell 代码好很多

        • 可读性更强

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-08-10
          • 2018-07-09
          • 2020-08-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多