Am 21.05.2016 um 05:45 schrieb [email protected]:
https://bz.apache.org/bugzilla/show_bug.cgi?id=59609

             Bug ID: 59609
            Summary: JSONPathPostProcessor not evaluating correctly
            Product: JMeter
            Version: 3.0
           Hardware: PC
             Status: NEW
           Severity: normal
           Priority: P2
          Component: HTTP
           Assignee: [email protected]
           Reporter: [email protected]

The JSONPathPostProcessor uses the follow to turn the JSON results to string,
however if toJSONString isn't used then all of the quotes will be removed.
As I have a problem connecting to bugzilla, I reply here.

Attached is a patch, that extracts JSON objects as JSON strings. Before JSON Objects would be stringified as Maps.

Regards,
 Felix


Current Example

With this Code (JSONPostProcessor 166-167):

Object obj = extractedValues.get(0);
String objAsString = obj != null ? obj.toString() : ""; //$NON-NLS-1$

Run with:

$.context

Against:

{
   "context": {
     "#v": "abc123",
     "#t": "string"
   }
}

Results in:

{#v: abc123, #t: string}

This is incorrect, all of the quotes have been removed.

It should be replaced with something more like:

String objAsString = "";
if (extractedValues instanceof JSONArray) {
  objAsString = new JSONObject((Map) extractedValues.get(0)).toJSONString();
}

Which when tested results:

{"#t":"string","#v":"abc123"}

This obviously needs to be extended for examples where more than one response
is returned.


>From bf9d451e42bf913e8262602a4c1149ddc6bbee66 Mon Sep 17 00:00:00 2001
From: Felix Schumacher <[email protected]>
Date: Sat, 21 May 2016 12:59:49 +0200
Subject: [PATCH] Bug59609 extract JSON Objects as JSON Strings.

---
 .../extractor/json/jsonpath/JSONPostProcessor.java | 44 +++++++++------
 .../jmeter/extractor/TestJSONPostProcessor.java    | 63 ++++++++++++++++++++++
 2 files changed, 91 insertions(+), 16 deletions(-)
 create mode 100644 test/src/org/apache/jmeter/extractor/TestJSONPostProcessor.java

diff --git a/src/components/org/apache/jmeter/extractor/json/jsonpath/JSONPostProcessor.java b/src/components/org/apache/jmeter/extractor/json/jsonpath/JSONPostProcessor.java
index 1f45b35..27b7838 100644
--- a/src/components/org/apache/jmeter/extractor/json/jsonpath/JSONPostProcessor.java
+++ b/src/components/org/apache/jmeter/extractor/json/jsonpath/JSONPostProcessor.java
@@ -21,6 +21,9 @@ package org.apache.jmeter.extractor.json.jsonpath;
 import java.io.Serializable;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
+
+import net.minidev.json.JSONObject;
 
 import org.apache.jmeter.processor.PostProcessor;
 import org.apache.jmeter.samplers.SampleResult;
@@ -125,11 +128,12 @@ public class JSONPostProcessor extends AbstractScopedTestElement implements Seri
                                         new StringBuilder(getComputeConcatenation()
                                                 ? extractedValues.size() * 20
                                                 : 1);
-                                for (Object stringExtracted : extractedValues) {
-                                    vars.put(currentRefName + "_" + index, 
-                                            stringExtracted != null ? stringExtracted.toString() : ""); //$NON-NLS-1$
+                                for (Object extractedObject : extractedValues) {
+                                    String extractedString = stringifyJSONObject(extractedObject);
+                                    vars.put(currentRefName + "_" + index,
+                                            extractedString); //$NON-NLS-1$
                                     if (getComputeConcatenation()) {
-                                        concat.append(stringExtracted)
+                                        concat.append(extractedString)
                                                 .append(JSONPostProcessor.JSON_CONCATENATION_SEPARATOR);
                                     }
                                     index++;
@@ -141,9 +145,9 @@ public class JSONPostProcessor extends AbstractScopedTestElement implements Seri
                             } else if (matchNumber == 0) {
                                 // Random extraction
                                 int matchSize = extractedValues.size();
-                                Object obj = extractedValues.get(JMeterUtils.getRandomInt(matchSize));
-                                vars.put(currentRefName, 
-                                        obj != null ? obj.toString() : ""); //$NON-NLS-1$
+                                int matchNr = JMeterUtils.getRandomInt(matchSize);
+                                placeObjectIntoVars(vars, currentRefName,
+                                        extractedValues, matchNr);
                             } else {
                                 // extract at position
                                 if (matchNumber > extractedValues.size()) {
@@ -155,20 +159,14 @@ public class JSONPostProcessor extends AbstractScopedTestElement implements Seri
                                     }
                                     vars.put(currentRefName, defaultValues[i]);
                                 } else {
-                                    Object obj = extractedValues.get(matchNumber - 1);
-                                    vars.put(currentRefName, 
-                                            obj != null ? obj.toString() : ""); //$NON-NLS-1$
+                                    placeObjectIntoVars(vars, currentRefName, extractedValues, matchNumber - 1);
                                 }
                             }
                         } else {
                             // else just one value extracted
-                            Object obj = extractedValues.get(0);
-                            String objAsString = 
-                                    obj != null ? obj.toString() : ""; //$NON-NLS-1$
-                            vars.put(currentRefName, 
-                                    objAsString); 
+                            placeObjectIntoVars(vars, currentRefName, extractedValues, 0);
                             if (matchNumber < 0 && getComputeConcatenation()) {
-                                vars.put(currentRefName + ALL_SUFFIX, objAsString);
+                                vars.put(currentRefName + ALL_SUFFIX, vars.get(currentRefName));
                             }
                         }
                         vars.put(currentRefName + REF_MATCH_NR, Integer.toString(extractedValues.size()));
@@ -187,6 +185,20 @@ public class JSONPostProcessor extends AbstractScopedTestElement implements Seri
         }
     }
 
+    private void placeObjectIntoVars(JMeterVariables vars, String currentRefName,
+            List<Object> extractedValues, int matchNr) {
+        Object obj = extractedValues.get(matchNr);
+        vars.put(currentRefName,
+                stringifyJSONObject(obj));
+    }
+
+    private String stringifyJSONObject(Object obj) {
+        if (obj instanceof Map) {
+            return new JSONObject((Map) obj).toJSONString();
+        }
+        return obj == null ? "" : obj.toString(); //$NON-NLS-1$
+    }
+
     public String getJsonPathExpressions() {
         return getPropertyAsString(JSON_PATH_EXPRESSIONS);
     }
diff --git a/test/src/org/apache/jmeter/extractor/TestJSONPostProcessor.java b/test/src/org/apache/jmeter/extractor/TestJSONPostProcessor.java
new file mode 100644
index 0000000..9b4bf95
--- /dev/null
+++ b/test/src/org/apache/jmeter/extractor/TestJSONPostProcessor.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+
+package org.apache.jmeter.extractor;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+
+import net.minidev.json.parser.JSONParser;
+import net.minidev.json.parser.ParseException;
+
+import org.apache.jmeter.extractor.json.jsonpath.JSONPostProcessor;
+import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.threads.JMeterContext;
+import org.apache.jmeter.threads.JMeterContextService;
+import org.apache.jmeter.threads.JMeterVariables;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestJSONPostProcessor {
+
+    private static final String VAR_NAME = "varName";
+
+    @Test
+    public void testBug59609() throws UnsupportedEncodingException,
+            ParseException {
+        JMeterContext context = JMeterContextService.getContext();
+        JSONPostProcessor processor = new JSONPostProcessor();
+        processor.setThreadContext(context);
+        processor.setRefNames(VAR_NAME);
+        SampleResult result = new SampleResult();
+        String innerValue = "{\"a\":\"one\",\"b\":\"two\"}";
+        String data = "{\"context\":" + innerValue + "}";
+        result.setResponseData(data.getBytes(StandardCharsets.UTF_8));
+        JMeterVariables vars = new JMeterVariables();
+        context.setVariables(vars);
+        context.setPreviousResult(result);
+
+        processor.setJsonPathExpressions("$.context");
+        processor.process();
+
+        JSONParser parser = new JSONParser(0);
+        Object expectedValue = parser.parse(innerValue);
+        Assert.assertEquals(expectedValue, parser.parse(vars.get(VAR_NAME)));
+        Assert.assertEquals("1", vars.get(VAR_NAME + "_matchNr"));
+    }
+
+}
-- 
2.7.4

Reply via email to