使用RegEx Extractor从JSON响应中提取多个值

时间:2011-11-14 17:55:23

标签: regex json jmeter

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

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

响应将包含许多部分,如上例所示。

我想在Jmeter中做的是通过JSON响应并按照我可以将返回的名称和描述作为一个条目进行迭代的方式拉出上面概述的每个部分。

到目前为止我能够做的是使用模板$ 1 $返回带有正则表达式提取器(“name”:“(。+?)”)的名称值。我想拉出名字和描述,但似乎无法让它发挥作用。我尝试使用正则表达式“name”:“(。+?)”,“description”:“(。+?)”,模板为$ 1 $$ 2 $,但没有任何成功。

在此示例中,有人知道如何使用正则表达式提取多个值吗?

4 个答案:

答案 0 :(得分:3)

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

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

它对断言有用。

答案 1 :(得分:2)

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

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

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

示意图如下:

  1. 在BeanShell PostProcessor的情况下:

    Thread Group
        . . .
        YOUR HTTP Request
            BeanShell PostProcessor    // added as child
        . . .
    
  2. 如果是BeanShell Sampler:

    Thread Group
        . . .
        YOUR HTTP Request
        BeanShell Sampler          // added separate sampler - after your
        . . .
    
  3. 在这种情况下,使用哪一个没有区别。

    bsh-sampler_extract-json-data

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

    取样器代码:

    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());
    }
    

    还有一组链接:


    <强> UPD。在08.2017:

    目前,JMeter已经设置了一些内置组件(从第三方项目合并)来处理JSON而无需编写脚本:

答案 2 :(得分:1)

我假设JMeter使用基于Java的正则表达式......这可能意味着没有命名捕获组。显然,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?"!将作为AND存储在JSON中并正确解析为{{1} }

答案 3 :(得分:0)

使用JMeter的Ubik Load Pack插件已经捐赠给JMeter核心,从版本3.0开始JSON Extractor,您可以通过以下测试计划这样做:

enter image description here

namesExtractor_ULP_JSON_PostProcessor config:

enter image description here

descriptionExtractor_ULP_JSON_PostProcessor config:

enter image description here

循环控制器循环结果:

enter image description here

计数器配置:

enter image description here

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

enter image description here

以下是您获得以下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 }]

enter image description here

与Beanshell解决方案相比:

  • 这是更“标准的方法”

  • 它比Beanshell代码

  • 表现得更好
  • 更具可读性