Unable to extract a value from json and use it in subsequent request - jmeter-5.0

My test receives the following json in response.
{"result":"success","additional-info":"{\"q-list\":[{\"tag\":\"un2-new tag2-empty\",\"description\":\"some description2\",\"q-id\":\"5c86fb8a-d9ce-4978-be4c-2c4b547c7868\",\"creation-year\":2020,\"creation-month\":11,\"creation-hour\":8,\"creation-minute\":48}],\"pagination-info\":{\"page-state\":\"004400100038000800000000000000080800000000000000302435633836666238612d643963652d343937382d626534632d326334623534376337383638f07ffffffef07ffffffe9fde9512dc65b09db4b903cca66a71aa0004\",\"partition-info\":{\"year\":2020,\"month\":11}}}"}
I want to extract q-id from the response and the use it in next request. I have created the following extractor.
and am using it as follows:
But I see that the value is not getting extracted.
What am I doing wrong?

Happy to accept other answers. I was able to solve the issue by using beanshell script. However, I still don't know why extracting value from Regular Expression Extractor didn't work.
Beanshell script
import com.eclipsesource.json.*;
//prev.setSuccessful(false);
try {
String jsonString = prev.getResponseDataAsString(); //response as string
log.info("received json string: "+jsonString);
JsonObject responseAsJsonObject = JsonObject.readFrom(jsonString); //convert response string as json
log.info("converted to object: "+responseAsJsonObject);
String additionalInfoString = responseAsJsonObject.get("additional-info").asString(); //get additional info string from json object
log.info("additional info as string: "+additionalInfoString);
JsonObject additionalInfoJsonObject = JsonObject.readFrom(additionalInfoString); //convert additional info string to json
log.info("additional info as object: "+additionalInfoJsonObject);
JsonArray questionListObject = additionalInfoJsonObject.get("questions-list").asArray(); //get questions list array
log.info("questions list: "+questionListObject );
JsonObject firstQuestionFromList = questionListObject.get(0).asObject(); //get 1st question
log.info("first question: "+firstQuestionFromList);
String questionID = firstQuestionFromList.get("question-id").asString();
log.info("question id of 1st question "+questionID);
vars.put("questionIDFromBeanShell",questionID); //use this in next request
// prev.setSuccessful(true);
} catch (Exception e){
log.info("error in processing beanshell script: ", e);
prev.setSuccessful(false);
}

Related

Fetch the JSONobject value to a variable which is inside the dynamically generated JSONobject

We have below JSON response which has dynamically getting one of the JSONobject which has other objects inside. Tried some of the solutions provided here, but unable to get the values, every time getting 'null'.
{
"Result": {
"12987654": {//this value 1298.. is dynamically getting generated at every response.
"Tests1": {
"test1": -0.85,
"test2": 0.016,
"tests3": "FAIL"
},
"Tests2": {
"test21": "PASS",
"test22": "PASS",
"test23": "FAIL"
}
}
}
}
Now Trying to get value of inside this dynamically (1298..) generating object, like Tests2.teset21.
If tried as
JSONPath js.get("Results.1298.Tests1.test1")//able to get the value. however here 1298 is hardcoded and this value changes in the next run.
If tried as below, getting value as null.
import com.google.gson.JsonObject;
JsonObject jsonObjectResponse = (JsonObject) new JsonParser().parse(responseInString);
JsonObject Result = jsonObjectResponse.get("loanResult").getAsJsonObject();
SysOut(Result)//gives null
OR, trying below also gives null
JsonElement jelement = new JsonParser().parse(responseInString);
JsonObject ResultObj = jelement.getAsJsonObject();
System.out.println("ResultObj value is: " + loanResultObj.get("tests21"));
Please guide how to get value inside of dynamically generating Jsonobject.
Finally after many attempts, could understand using Gson to get the value. For my issue, the id which dynamic goes from Request. With below code could solve issue:
Gson gsonResp = new Gson();
String responseInString = response.asString();
JsonObject jsonObjectNewResponse = gsonResp.fromJson(responseInString, JsonObject.class);
String test12 = jsonObjectNewResponse.getAsJsonObject("Result").getAsJsonObject(<dynamicID which is been extracted from Req in the form of String>). getAsJsonObject("test1").get("test12").getAsString();

Evaluate expressions as well as regex in single field in custom processors of Nifi

In my custom processor I have added below field
public static final PropertyDescriptor CACHE_VALUE = new PropertyDescriptor.Builder()
.name("Cache Value")
.description("Cache Value")
.required(true)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
.build();
Where I expect to read flowfile attributes like ${fieldName}
as well as regex like .* to read full content or some part of content like $.nodename.subnodename
For that I have added below code
for (FlowFile flowFile : flowFiles) {
final String cacheKey = context.getProperty(CACHE_KEY).evaluateAttributeExpressions(flowFile).getValue();
String cacheValue = null;
cacheValue = context.getProperty(CACHE_VALUE).evaluateAttributeExpressions(flowFile).getValue();
if (".*".equalsIgnoreCase(cacheValue.trim())) {
final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
session.exportTo(flowFile, bytes);
cacheValue = bytes.toString();
}
cache.put(cacheKey, cacheValue);
session.transfer(flowFile, REL_SUCCESS);
}
How to achieve this one some part of content like $.nodename.subnodename.
Do I need to parse the json or is there any other way?
You will either have to parse the JSON yourself, or use an EvaluateJsonPath processor before reaching this processor to extract content values out to attributes via JSON Path expressions, and then in your custom code, reference the value of the attribute.

null string parameter in body of POST request to WebAPI2 service

I have an action defined in a WebAPI2 controller as follows:
[HttpPost]
[Route("DataImport/Product/")]
public DataImportJournalEntry ImportData([FromBody] string base64)
{
return _dataImportService.Import(Convert.FromBase64String(base64));
}
and I'm building a request, using RestSharp, as follows:
var base64 = {4Kb xml file loaded and encoded to base64}
var client = new RestClient(Config.BaseAddress);
var request = new RestRequest("DataImport/Product/", Method.POST);
request.AddParameter("base64", base64, ParameterType.GetOrPost);
request.AddHeader("accepts", "application/json");
var response = client.Execute<DataImportJournalEntry>(request);
The routing is correct as the action is called but the base64 parameter is null on the server side?
Found it..when using the FromBody attribute there can be only one parameter in the body and WebAPI is looking for it as ={value} not as you would expect {key}={value}. So I simply passed the parameter name as an empty string in the test:
...
var request = new RestRequest("DataImport/Product/", Method.POST);
request.AddParameter("", base64);
...
More details here: http://encosia.com/using-jquery-to-post-frombody-parameters-to-web-api/

Json.Net for serializing an object graph

I was using the .Net built in JavaScriptSerializer() to Serialize a JSON string coming from a webpage.
I heard that Newtonsoft.Json.Net have a better serializer, so I thought I would give it a try.
I load my json string, here is a sample.
jsonString = "{\"jName\":\"MB-CEF3-4\",\"StartDate\":\"08/20/2013 00:00\",\"EndDate\":\"08/29/2013 00:00\",\"JType\":\"General\",\"SetupParams\":[
{\"Name\":\"PTitle\",\"Title\":\"01. Period Title\",\"Type\":\"text\",\"Value\":\"TestName\"},
{\"Name\":\"PStart\",\"Title\":\"02. Period Start\",\"Type\":\"datetime\",\"Value\":\"08/20/2013\"},
{\"Name\":\"Target\",\"Title\":\"03. Target\",\"Type\":\"int\",\"Value\":\"1\"},
{\"Name\":\"URL\",\"Title\":\"04. Completion Report URL\",\"Type\":\"url\",\"Value\":\"http://www.example.com\"},
{\"Name\":\"FormTitle\",\"Title\":\"05. Form Title\",\"Type\":\"text\",\"Value\":\"ct\"},
{\"Name\":\"nvTypes\",\"Title\":\"{B6E71787-EB51-45CF-B408-552F79AF2E7B}\",\"Type\":\"nvc\",\"Value\":\"Use of nv tools\"}, {\"Name\":\"NVCoachingTypes\",\"Title\":\"\",\"Type\":\"nvc\",\"Value\":\"\"}]}";
JavaScriptSerializer scs = new JavaScriptSerializer();
Dictionary<String, Object> aps = (Dictionary<String, Object>)scs.DeserializeObject(ActSetupConfigs);
I then would pass this Dictionary into another worker class, where it is deserialized..
I was using: var parameters = ((object[])Parameters["SetupParams"]);
and it would load the an array of objects.
I tried to do the same with Json.Net
Dictionary<String, Object> aps = JsonConvert.DeserializeObject<Dictionary<String, Object>>(ActSetupConfigs);
but when I try to deserialize it I don't get an array of objects, instead the sub collection of the array is just a string....so it throws an exception. How can I use Json.net to serialize all the sub-collections?
The sub-collection of the SetupParams array is not a string, it is a JToken, which is a generic container object that JSON.Net uses to hold a JSON structure. Fortunately, it is easy to extract values from a JToken. Try using this code instead.
JToken aps = JToken.Parse(jsonString);
foreach (JToken param in aps["SetupParams"])
{
Console.WriteLine("Name: " + param["Name"].Value<string>());
Console.WriteLine("Title: " + param["Title"].Value<string>());
Console.WriteLine("Type: " + param["Type"].Value<string>());
Console.WriteLine("Value: " + param["Value"].Value<string>());
Console.WriteLine();
}
You can parse the above json response using json.net like,
dynamic initialresp=JValue.Parse(jsonString);
string jname=Convert.ToString(initialresp.jname);
...
...
dynamic setupparams=JArray.Parse(Convert.ToString(initialresp.SetupParams));
foreach(var item in setupparams)
{
string name=Convert.Tostring(item.Name);
string title=Convert.Tostring(item.Title);
...
...
}
Hope this helps.

How to retrieve photo previews in app.net

When I have an app.net url like https://photos.app.net/5269262/1 - how can I retrieve the image thumbnail of the post?
Running a curl on above url shows a redirect
bash-3.2$ curl -i https://photos.app.net/5269262/1
HTTP/1.1 301 MOVED PERMANENTLY
Location: https://alpha.app.net/pfleidi/post/5269262/photo/1
Following this gives a html page that contains the image in a form of
img src='https://files.app.net/1/60621/aWBTKTYxzYZTqnkESkwx475u_ShTwEOiezzBjM3-ZzVBjq_6rzno42oMw9LxS5VH0WQEgoxWegIDKJo0eRDAc-uwTcOTaGYobfqx19vMOOMiyh2M3IMe6sDNkcQWPZPeE0PjIve4Vy0YFCM8MsHWbYYA2DFNKMdyNUnwmB2KuECjHqe0-Y9_ODD1pnFSOsOjH' data-full-width='2048' data-full-height='1536'
Inside a larger block of <div>tags.
The files api in app.net allows to retrieve thumbnails but I somehow don't get the link between those endpoints and above urls.
The photos.app.net is just a simple redirecter. It is not part of the API proper. In order to get the thumbnail, you will need to fetch the file directly using the file fetch endpoint and the file id (http://developers.app.net/docs/resources/file/lookup/#retrieve-a-file) or fetch the post that the file is included in and examine the oembed annotation.
In this case, you are talking about post id 5269262 and the URL to fetch that post with the annotation is https://alpha-api.app.net/stream/0/posts/5269262?include_annotations=1 and if you examine the resulting json document you will see the thumbnail_url.
For completeness sake I want to post the final solution for me here (in Java) -- it builds on the good and accepted answer of Jonathon Duerig :
private static String getAppNetPreviewUrl(String url) {
Pattern photosPattern = Pattern.compile(".*photos.app.net/([0-9]+)/.*");
Matcher m = photosPattern.matcher(url);
if (!m.matches()) {
return null;
}
String id = m.group(1);
String streamUrl = "https://alpha-api.app.net/stream/0/posts/"
+ id + "?include_annotations=1";
// Now that we have the posting url, we can get it and parse
// for the thumbnail
BufferedReader br = null;
HttpURLConnection urlConnection = null;
try {
urlConnection = (HttpURLConnection) new URL(streamUrl).openConnection();
urlConnection.setDoInput(true);
urlConnection.setDoOutput(false);
urlConnection.setRequestProperty("Accept","application/json");
urlConnection.connect();
StringBuilder builder = new StringBuilder();
br = new BufferedReader(
new InputStreamReader(urlConnection.getInputStream()));
String line;
while ((line=br.readLine())!=null) {
builder.append(line);
}
urlConnection.disconnect();
// Parse the obtained json
JSONObject post = new JSONObject(builder.toString());
JSONObject data = post.getJSONObject("data");
JSONArray annotations = data.getJSONArray("annotations");
JSONObject annotationValue = annotations.getJSONObject(0);
JSONObject value = annotationValue.getJSONObject("value");
String finalUrl = value.getString("thumbnail_large_url");
return finalUrl;
} .......

Resources