Postman test - How can I search the entire response for a specific value? - json

Sorry for the noob question.
Using Postman, how can I search the entire response for a specific value? In this case the value I am using as my assertion would be let’s say “222222”, this has been set as an environment variable (“provId”) in another request and I need to be able to assert that it appears in this second request.
Below is a small snippet of the response I’m working with, the acual response would be much larger and the value “222222” could appear anywhere within.
[
{
“eventId”: “123456”,
“mappings”: [{
“provider”: “ABC”,
“providerId”: “111111”,
“confidence”: 1.0
}
]
},
{
“eventId”: “246810”,
“mappings”: [{
“provider”: “ABC”,
“providerId”: “222222”,
“confidence”: 1.0
}
]
},
{
“eventId”: “135791”,
“mappings”: [{
“provider”: “ABC”,
“providerId”: “333333”,
“confidence”: 1.0
}
]
}
]
I have managed to write a bit of code to check the correct value from the 1st object (below) but I need it to search the whole response.
const body = pm.response.json();
pm.test(“placeholder” + pm.variables.get(“provId”), function() {
pm.response.to.have.jsonBody("[0][mappings].[0][providerId]",
pm.variables.get(“provId”) );
});

let a =
[
{
"eventId": "123456",
"mappings": [{
"provider": "ABC",
"providerId": "111111",
"confidence": 1.0
}
]
},
{
"eventId": "246810",
"mappings": [{
"provider": "ABC",
"providerId": "222222",
"confidence": 1.0
}
]
},
{
"eventId": "135791",
"mappings": [{
"provider": "ABC",
"providerId": "333333",
"confidence": 1.0
}
]
}
]
console.log(a.find(elem => elem.mappings[0].providerId === "333333"))
use array.find
Update as per comment , if you dont know the mapping index then:
console.log(a.find(elem => {
return elem.mappings.find(items=>items.providerId==="333333")
}
))

Solution;
var resp = pm.response.json();
console.log(resp);
for (var i = 0;i<resp.length;i++)
{
if (resp[i].mappings[0].providerId == pm.variables.get(“provId”))
{
console.log("PASSED TEST : " +resp[i].eventId);
}
else
{
console.log("FAILED TEST : " +resp[i].eventId);
}
}

Related

Extract nested JSON array response object using JS Lodash in Postman

I want to learn how to use Lodash to extract variables from a JSON response because the traditional methods explained on other Postman questions do not explain an easy way to do this as I used to do it with json path in Jmeter.
I need to translate the following json paths to a Lodash expression that returns the same values as this JSON paths
1. FlightSegmentsItinerary[*].Flights[*].Key
2. $..Flights[*].Key
3. Travelers[*].[?(#.TypeCode == "INF")].FirstName (returns the name of the passangers whose type code are == "INF")
JSON Response:
{
"Travelers": [
{
"TypeCode": "ADT",
"FirstName": "FULANO",
"Surname": "LAZARO",
"Key": "1.1"
},
{
"TypeCode": "INF",
"FirstName": "MENGANO",
"Surname": "XULO",
"Key": "2.2"
}
],
"FlightSegmentsItinerary": [
{
"Flights": [
{
"Key": "1"
},
{
"Key": "2"
}
]
}
]
}
So far I was able to extract the travelers Keys (Travelers[*].Key) using this:
var jsonData = pm.response.json();
var travelerKeys = _.map(jsonData.Travelers, 'Key');
console.log("travelerKeys: " + travelerKeys);
Output: travelerKeys: 1.1,2.2
As you can see, the JSON path:
Travelers[*].Key
Looks like this in Lodash:
var travelerKeys = _.map(jsonData.Travelers, 'Key');
for this case.
var jsonData = {
"Travelers": [{
"TypeCode": "ADT",
"FirstName": "FULANO",
"Surname": "LAZARO",
"Key": "1.1"
},
{
"TypeCode": "INF",
"FirstName": "MENGANO",
"Surname": "XULO",
"Key": "2.2"
}
],
"FlightSegmentsItinerary": [{
"Flights": [{
"Key": "1"
},
{
"Key": "2"
}
]
}]
}
// 1. FlightSegmentsItinerary[*].Flights[*].Key
console.log( _(jsonData.FlightSegmentsItinerary).flatMap('Flights').map('Key') )
//2. $..Flights[*].Key
console.log( _.chain(jsonData).values().flatten().find('Flights').values().flatten().map('Key') )
//3. Travelers[*].[?(#.TypeCode == "INF")].FirstName (returns the name of the passangers whose type code are == "INF")
console.log( _(jsonData.Travelers).filter(['TypeCode', 'INF']).map('FirstName') )
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.11/lodash.min.js"></script>
Another option might be to try JavaScript libraries such as https://github.com/dchester/jsonpath
var jsonData = {
"Travelers": [{
"TypeCode": "ADT",
"FirstName": "FULANO",
"Surname": "LAZARO",
"Key": "1.1"
},
{
"TypeCode": "INF",
"FirstName": "MENGANO",
"Surname": "XULO",
"Key": "2.2"
}
],
"FlightSegmentsItinerary": [{
"Flights": [{
"Key": "1"
},
{
"Key": "2"
}
]
}]
}
console.log(jsonpath.query(jsonData, '$.FlightSegmentsItinerary[*].Flights[*].Key'))
console.log(jsonpath.query(jsonData, '$..Flights[*].Key'))
console.log(jsonpath.query(jsonData, '$.Travelers..[?(#.TypeCode == "INF")].FirstName'))
<script src="https://cdn.jsdelivr.net/npm/jsonpath#1.0.2/jsonpath.min.js"></script>
Because Postman doesn't support fetch and XMLHttpRequest, the jsonpath.min.js file contents can be saved in environment variable, and then eval(pm.environment.get('jsonpath')); before use as described in
https://community.getpostman.com/t/adding-external-libraries-to-postman/1971/4
You have to tell Postman which Sandbox module you going to use using require function(refer below code). The error you get has some issue with Postman few of them works few of them not Here they are talking
and Here is the postman issue tracker
the code I tried and worked for me as
const moment = require('lodash');
var keys = _.chain(obj.Travelers)
.map("Key")
.flatten()
.unique()
.value();
console.log(keys);
output
Array:[]
0 : "1.1"
1 : "2.2"
form more details you can look at
Postman Sandbox API reference
postman-and-lodash-the-perfect-partnership

Set next step for the waterfall dialogue in Microsoft BotBuilder NodeJS SDK

I am using Microsoft Bot Framework for my facebook messenger bot. I want to load the dialog data from json files instead of hard coding in the js file. I would like to configure the next step in the dialog, based on result from the "current" step, which is part of the json file configuration, something like this.
{
"name": "welcome",
"type": "waterfall",
"steps": [
{
"id": 0,
"data": [
{
"type": "text",
"value": "Hey, It's nice to meet you."
},
{
"type": "quickReplies",
"value": "What do you want to do next?",
"options": [
{
"text": "some option 1",
"value": "option1"
},
{
"text": "some option 2",
"value": "option2"
}
]
}
],
"next": [
{
"result": "option1",
"action": "goto step 2"
},
{
"result": "option2",
"action": "goto step 5"
}
]
}
]
}
I would like to process all the incoming messages and respond with correct dialog or correct step in the dialog for the user.
I am trying something like this;
handleMessage = function (session) {
var step = session.dialogData["BotBuilder.Data.WaterfallStep"] || 0;
// check response data from previou step and identify the next step.
// set the waterfall step id
session.dialogData["BotBuilder.Data.WaterfallStep"] = 2;
session.send("Hello");
}
var bot = new builder.UniversalBot(connector, function (session) {
handleMessage(session);
})
.set('storage',tableStorage);
With this code, I am always getting step as zero for session.dialogData["BotBuilder.Data.WaterfallStep"] even after setting this to a different number.
Also, as soon as I set the waterfall step number, all other state data that is stored in my table storage for this conversation is gone.
Storage data before setting waterfall step:
{
"BotBuilder.Data.SessionState": {
"callstack": [
{
"id": "*:/",
"state": {
"BotBuilder.Data.WaterfallStep": 0
}
},
{
"id": "*:welcome",
"state": {
"BotBuilder.Data.WaterfallStep": 1
}
},
{
"id": "BotBuilder:prompt-text",
"state": {
"options": {
"prompt": {
"type": "message",
"agent": "botbuilder",
"source": "facebook",
"address": {
"id": "mid.$cAAAlr-0LRH9niO21L1hV6hs83GuJ",
"channelId": "facebook",
"user": {
"id": "XXXX",
"name": "XXXX"
},
"conversation": {
"isGroup": false,
"id": "XX"
},
"bot": {
"id": "XXX",
"name": "XXX"
},
"serviceUrl": "https://facebook.botframework.com"
},
"text": "what do you want to next"
//ignored for simplicity
},
"promptAfterAction": true,
"libraryNamespace": "*"
},
"turns": 0,
"lastTurn": 1517594116372,
"isReprompt": false
}
}
],
"lastAccess": 1517594112740,
"version": 0
}
}
After I set the waterfall step:
{
"BotBuilder.Data.SessionState": {
"callstack": [
{
"id": "*:/",
"state": {
"BotBuilder.Data.WaterfallStep": 2
}
}
],
"lastAccess": 1517602122416,
"version": 0
}
}
Interestingly the step number is saved to the database (but in session state) but my "session" variable do not have this value anywhere. Also, even after configuring custom state service, the serviceUrl is still https://facebook.botframework.com which I thought is the default state service used if there is no state service set for the bot.
Per your code, as your bot actually contains only one waterfall step: handleMessage(session);, which raised your issue. You can consider to create multiple dialogs from json configration instead of complex waterfall steps.
Here is my quick test, for your information:
const json = `
[{
"name": "welcome",
"type": "waterfall",
"steps": [
{
"id": 0,
"data": [
{
"type": "text",
"value": "Hey, It's nice to meet you."
},
{
"type": "quickReplies",
"value": "What do you want to do next?",
"options": [
{
"text": "some option 1",
"value": "option1"
},
{
"text": "some option 2",
"value": "option2"
}
]
}
],
"next": [
{
"result": "option1",
"action": "dialog2"
},
{
"result": "option2",
"action": "dialog3"
}
]
}
]
},{
"name":"dialog2",
"type": "waterfall",
"steps": [
{
"data": [
{
"type": "text",
"value": "Hey, this is dialig2."
}]
}
]
},{
"name":"dialog3",
"type": "waterfall",
"steps": [
{
"data": [
{
"type": "text",
"value": "Hey, this is dialig3."
}]
}
]
}]
`;
const generateSignleStep = (step) => {
return (session, args, next) => {
step.forEach(sentence => {
switch (sentence.type) {
case 'quickReplies':
let choices = sentence.options.map(item => {
return item.value
});
let card = new builder.ThumbnailCard(session)
.text(sentence.value)
.buttons(sentence.options.map(choice => new builder.CardAction.imBack(session, choice.value, choice.text)))
let message = new builder.Message(session).addAttachment(card);
builder.Prompts.choice(session, message, choices);
break;
case 'text':
default:
session.send(sentence.value)
break;
}
})
}
}
const generatenextAction = (actions) => {
return (session, args, next) => {
const response = args.response;
actions.map(action => {
if (action.result == response.entity) {
session.beginDialog(action.action);
}
})
}
}
const generateWaterfallSteps = (steps) => {
let waterfall = [];
steps.forEach(step => {
waterfall.push(generateSignleStep(step.data));
if (step.next) {
waterfall.push(generatenextAction(step.next));
}
});
return waterfall;
}
var bot = new builder.UniversalBot(connector);
const jsonobj = JSON.parse(json);
jsonobj.forEach(dialog => {
bot.dialog(dialog.name, generateWaterfallSteps(dialog.steps))
.triggerAction({
matches: new RegExp(dialog.name, "g")
})
});
The result is:

JSON transformation in node.js

I want to transform my data from one json structure to another. What is the best way to do it?
Here is my original resource (customer) structure is:
{
"id": "123",
"data": {
"name": "john doe",
"status": "active",
"contacts": [
{
"email": "john#email.com"
},
{
"phone": "12233333"
}
]
}
}
I want to change it to:
{
"id": "123",
"name": "john doe",
"status": "active",
"contacts": [
{
"email": "john#email.com"
},
{
"phone": "12233333"
}
]
}
Keeping in mind that I might have an array of resources(customers) being returned in GET /customers cases. I want to change that to an array of new data type.
If customer object is array of object then below will help you to get desire format result
var result = customerObj.map(x => {
return {
id: x.id,
name: x.data.name,
status: x.data.status,
contacts: x.data.contacts
};
});
here I have used Object.assign() it will be helpful to you
var arr={
"id": "123",
"data": {
"name": "john doe",
"status": "active",
"contacts": [
{
"email": "john#email.com"
},
{
"phone": "12233333"
}
]
}
}
arr=Object.assign(arr,arr.data);
delete arr['data'];
console.log(arr);
You have to Json.parse the json into variable, and then loop through the array of objects, changes the object to the new format, and then JSON.stringify the array back to json.
Example code
function formatter(oldFormat) {
Object.assign(oldFormat, oldFormat.data);
delete oldFormat.data;
}
let parsedData = JSON.parse(Oldjson);
//Take care for array of results or single result
if (parsedData instanceof Array) {
parsedData.map(customer => formtter(customer));
} else {
formatter(parsedData);
}
let newJson = JSON.stringify(parsedData);
console.log(newJson);
Edit
I made the formatter function cleaner by using Kalaiselvan A code

How to properly pass Json data to fusioncharts? -Multisiries-

First time poster, thanks for the attention.
Using web api to generate object to be consumed by fusioncharts (Multiseries). Object is produced as array of 2 classes (ChartCategories and ChartSeries) output seems fine and is retrieved in angular controller as data. yet after building up $scope.categories and $scope.dataset using data, I am unable to generate the chart with error 'No data to display'.
Partial Html template for chart:
<div id = "Div1">
<fusioncharts
width="400"
height="200"
type="mscolumn2d"
chart="{{attrs}}"
categories="{{categories}}"
dataset="{{dataset}}"
></fusioncharts>
</div>
data retrieved from web api: (copied + pasted)
[
[
{
"category": [
{
"label": "7/18/2014 9:30:01 AM"
},
{
"label": "7/18/2014 9:40:00 AM"
},
{
"label": "7/18/2014 9:50:00 AM"
}
]
},
null,
null
],
[
null,
{
"seriesname": "Free_Memory",
"renderas": "Line",
"data": [
{
"value": "6632"
},
{
"value": "5136"
},
{
"value": "6376"
}
]
},
{
"seriesname": "Page_Life_Exp",
"renderas": "Line",
"data": [
{
"value": "48859"
},
{
"value": "49458"
},
{
"value": "50057"
}
]
}
]
]
and in angular, I set the $scope.categories and $scope.dataset like so: $scope.attr is hard coded for the time being.
$scope.categories = data[0][0];
$scope.dataset = data[1][1];
What is needed in order to generate the graph?
Refer to http://jsfiddle.net/ayanonly1/yh1cvjqw/
I think following changes will make the chart live.
$scope.categories = [data[0][0]];
$scope.dataset = data[1].slice(1);

evaluating json object returned from controller and attaching it to prepopulate attribute of tokeninput

I am using loopjs tokeninput in a View. In this scenario I need to prePopulate the control with AdminNames for a given Distributor.
Code Follows :
$.getJSON("#Url.Action("SearchCMSAdmins")", function (data) {
var json=eval("("+data+")"); //doesnt work
var json = {
"users": [
eval("("+data+")") //need help in this part
]
}
});
$("#DistributorCMSAdmin").tokenInput("#Url.Action("SearchWithName")", {
theme: "facebook",
preventDuplicates: true,
prePopulate: json.users
});
There is successful return of json values to the below function. I need the json in the below format:
var json = {
"users":
[
{ "id": "1", "name": "USER1" },
{ "id": "2", "name": "USER2" },
{ "id": "3", "name": "USER3" }
]
}