Trying to get a JSONPath array of all leaves on json object - go

New to Go. My first project is to compare a NodeJS proxy and a Go proxy for account number tokenization. I have been doing NodeJS for a few years and am very comfortable with it. My proxies will not know the format of any request or response from the target servers. But it does have configurations coming from Redis/MongoDB that is similar to JSONPath expression. These configurations can change things like the target server/path, query parameters, headers, request body and response body.
For NodeJS, I am using deepdash's paths function to get an array of all the leaves in a JSON object in JSONPath format. I am using this array and RegEx to find my matching paths that I need to process from any request or response body. So far, it looks like I will be using gjson for my JSONPath needs, but it does not have anything for the paths command I was using in deepdash.
Will I need to create a recursive function to build this JSONPath array myself, or does anyone know of a library that will produce something similar?
for example:
{
"response": {
"results": [
{
"acctNum": 1234,
"someData": "something"
},
{
"acctNum": 5678,
"someData": "something2"
}
]
}
}
I will get an array back in the format:
[
"response.results[0].acctNum",
"response.results[0].someData",
"response.results[1].acctNum",
"response.results[1].someData"
]
and I can then use my filter of response.results[*].acctNum which translates to response\.results\[.*\]\.acctNum in Regex to get my acctNum fields.
From this filtered array, I should be able to use gjson to get the actual value, process it and then set the new value (I am using lodash in NodeJS)

There are a number of JSONPath implementations in GoLang. And I cannot really give a recommendation in this respect.
However, I think all you need is this basic path: $..*
It should return in pretty much any implementation that is able to return pathes instead of values:
[
"$['response']",
"$['response']['results']",
"$['response']['results'][0]",
"$['response']['results'][1]",
"$['response']['results'][0]['acctNum']",
"$['response']['results'][0]['someData']",
"$['response']['results'][1]['acctNum']",
"$['response']['results'][1]['someData']"
]
If I understand correctly this should still work using your approach filtering using RegEx.
Go SONPath implementations:
http://github.com-PaesslerAG-jsonpath
http://github.com-bhmj-jsonslice
http://github.com-ohler55-ojg
http://github.com-oliveagle-jsonpath
http://github.com-spyzhov-ajson
http://github.com-vmware-labs-yaml-jsonpath

Related

Powerautomate Parsing JSON Array

I've seen the JSON array questions here and I'm still a little lost, so could use some extra help.
Here's the setup:
My Flow calls a sproc on my DB and that sproc returns this JSON:
{
"ResultSets": {
"Table1": [
{
"OrderID": 9518338,
"BasketID": 9518338,
"RefID": 65178176,
"SiteConfigID": 237
}
]
},
"OutputParameters": {}
}
Then I use a PARSE JSON action to get what looks like the same result, but now I'm told it's parsed and I can call variables.
Issue is when I try to call just, say, SiteConfigID, I get "The output you selected is inside a collection and needs to be looped over to be accessed. This action cannot be inside a foreach."
After some research, I know what's going on here. Table1 is an Array, and I need to tell PowerAutomate to just grab the first record of that array so it knows it's working with just a record instead of a full array. Fair enough. So I spin up a "Return Values to Virtual Power Agents" action just to see my output. I know I'm supposed to use a 'first' expression or a 'get [0] from array expression here, but I can't seem to make them work. Below are what I've tried and the errors I get:
Tried:
first(body('Parse-Sproc')?['Table1/SiteConfigID'])
Got: InvalidTemplate. Unable to process template language expressions in action 'Return_value(s)_to_Power_Virtual_Agents' inputs at line '0' and column '0': 'The template language function 'first' expects its parameter be an array or a string. The provided value is of type 'Null'. Please see https://aka.ms/logicexpressions#first for usage details.'.
Also Tried:
body('Parse-Sproc')?['Table1/SiteconfigID']
which just returns a null valued variable
Finally I tried
outputs('Parse-Sproc')?['Table1']?['value'][0]?['SiteConfigID']
Which STILL gives me a null-valued variable. It's the worst.
In that last expression, I also switched the variable type in the return to pva action to a string instead of a number, no dice.
Also, changed 'outputs' in that expression for 'body' .. also no dice
Here is a screenie of the setup:
To be clear: the end result i'm looking for is for the system to just return "SiteConfigID" as a string or an int so that I can pipe that into a virtual agent.
I believe this is what you need as an expression ...
body('Parse-Sproc')?['ResultSets']['Table1'][0]?['SiteConfigID']
You can see I'm just traversing down to the object and through the array to get the value.
Naturally, I don't have your exact flow but if I use your JSON and load it up into Parse JSON step to get the schema, I am able to get the result. I do get a different schema to you though so will be interesting to see if it directly translates.

Use Jmeter function value as variable in request

I'm trying to wrap my head around Jmeter functions and how to actually use them in an HTTP JSON request. All examples I've found on function use them as titles in HTTP requests, which is not helpful.
All I want to do is this, and then use that variable in my POST request. But that doesn't work and I have no clue why not.
...
"dates": {
"invoiceDate": ${testdate},
...
In all examples I've seen, the function is set as the HTTP sampler name, like so:
This is not helpful at all since I can't use that as a variable.
I don't think 20211 is the valid year, do you mean 2021?
If you put the function inside User Defined Variables - it will be evaluated only once and won't be random, you should rather inline it into the request body as User Defined Variables are evaluated only once, when the test starts
If you're trying to post JSON - I think you should surround the function with quotation marks, otherwise the JSON will be invalid. Suggested change:
{
"dates" : {
"invoiceDate": "${__RandomDate(,,2021-06-20,,)}"
}
}

Is there a way to properly drill down into a JSON response with random property names

I'm trying to test an API response where key values are randomized alphanumerics. This is making it difficult for me to drill down into the JSON response to get the data I want to test.
I am using SuperTest/Mocha/Chai. At this point I'm just trying to test to see if the property 'id', 'name', and 'pattern' exist, and to verify the values of those properties.
Unfortunately since the parent of those properties is a randomized value, i've been unable to access it.
I'm new to API testing in general, so I apologize if I'm not including some important information. Normally I would do something like this:
Example of expects I normally write:
end(function(err, res) {
expect(res.body).to.have.property('id');
expect(res.body.id).to.equal(0);
}
So far, the only way I've found to do it is to put response.text into a variable, then use split and splice to separate out the data I want. This is ugly and probably inefficient.
Example JSON I'm working with:
{ idTag1: 'randomValue',
idTag2:
{ 'randomValue':
{ id: 'an integer',
name: 'a basic string',
pattern: 'a basic string'
}
}
}

How to assert a JSON response which have results in random order every time in JMeter?

I am using JSON Assertion to assert if a JSON path exists. Suppose I have a JSON response of an array of 'rooms' that 'contains' an array of cabinets, just like the following example
"rooms":
[
{
"cabinets":
[
{
"id":"HFXXXX",
"locationid":null,
"name":"HFXXXX",
"type":"Hosp"
},
{
"id":"HFYYYY",
"locationid":null,
"name":"HFYYYY",
"type":"Hosp"
},
{
"id":"HFZZZZ",
"locationid":null,
"name":"HFZZZZ",
"type":"Hosp"
}
],
"hasMap":false,
"id":"2",
"map":
{
"h":null,
"w":null,
"x":null,
"y":null
},
"name":"Fantastic Room#3"
}
],
[
{ "cabinets":
[
{
"id":"HFBBBB",
"locationid":null,
"name":"HFBBBB",
"type":"Hosp"
}
],
"hasMap":false,
"id":"3",
"map":
{
"h":null,
"w":null,
"x":null,
"y":null
},
"name":"BallRoom #4"
}
]
I want to Make sure that the 'id' of all the cabinets are correct, therefore I define the JSON path as rooms[*].cabinets[*].id and expect the value to be ["HFXXXX","HFYYYY","HFZZZZ","HFBBBB"]
This works perfectly except that sometimes the values are returned in a different order["HFBBBB", "HFXXX","HFYYYY","HFZZZZ"] instead of ["HFXXXX","HFYYYY","HFZZZZ","HFBBBB"], hence the assertion will fail. The problem is with the order of the returned array and not the values themselves.
Is there a way to sort the order of a response before Asserting and keep using the JSON assertion? or the only way of doing this is extracting the value i want to assert against and use it in JSR223 Assertion (groovy or javascript)?
if that is the case can you show me an example of how I could do it in JSR223 plugin.
I would recommend using a dedicated library, for instance JSONAssert, this way you will not have to reinvent the wheel and can compare 2 JSON objects in a single line of code
Download jsonassert-x.x.x.jar and put it somewhere to JMeter Classpath
Download suitable version of JSON in Java library and put it to JMeter Classpath as well. If you're uncertain regarding what is "JMeter Classpath" just drop the .jars to "lib" folder of your JMeter installation
Restart JMeter so it would be able to load the new libraries
Add JSR223 Assertion as a child of the request which returns the above JSON
Put the following code into "Script" area:
def expected = vars.get('expected')
def actual = prev.getResponseDataAsString()
org.skyscreamer.jsonassert.JSONAssert.assertEquals(expected, actual, false)
It will compare the response of the parent sampler with the contents of ${expected} JMeter Variable, the order of elements, presence of new lines, formatting do not matter, it compares only keys and values
In case of mismatch you will have the error message stating that as the Assertion Result and the full debugging output will be available in STDOUT (console where you started JMeter from)

How to access nested array values in JSON response and use them in a loop in next service in JMeter

I am working on a POST service that give JSON response.
I have to extract certain value from the JSON response. example-
`{
"Result":
{ "Id":22
"StartTime":
"EndTime":
"RoutePoints":
[{ "Id":675,
}
{ "Id":676,
}
]
}
} `
My first part of the question-
How do I refer the "Id" variable inside the "RoutePoint" array using regular expression extractor? I can simply use "Id", but I also have an "Id" variable outside the "RoutePoint" array.
Secondly-
How do I take the "Id" each time and run them in a loop in the following service? Example- I take "Id=675" and perform a job, then take "Id=676" and perform that same job. Please be as detailed as possible, I am new to JMeter.
I would recommend going for JSON Path PostProcessor which is available since JMeter 3.0
Add JSON Path PostProcessor as a child of the request which returns above JSON and configure it as follows:
Variable Names: anything meaningful, i.e. Id
JSON Path Expressions: $..RoutePoints.*.Id
Match Numbers: -1
You should get variables like:
Id_1=675
Id_2=676
Id_matchNr=2
suitable for iteration with i.e. ForEach Controller
Demo:
References:
JSONPath - XPath for JSON
Advanced Usage of the JSON Path Extractor in JMeter

Resources