How to compare two JSON responses on Robot Framework? - json

I'm trying to find a library that contains a keyword to help me with that and didn't succeed.
What I'm doing at the moment is converting each JSON response to a dictionary and then comparing the dictionaries, but I hate it.
I was trying to find similar libraries and found this python code, but I don't know how to make this function works to me.
def _verify_json_file(self, result, exp):
'''
Verifies if two json files are different
'''
with open(exp) as json_data:
data = re.sub(ID, ID_REP, json_data.read())
expected = JSON.loads(data)
differences = jsondiff.diff(expected, result, syntax='explicit')
if not differences :
return True
if differences == expected or differences == result:
raise AssertionError("ERROR! Jsons have different structure")
return False

APPROACH#0
To make the above function work for you you just have to create a python file and put your function in that file and keep that file in the PYTHONPATH and use the same in your robot code by calling it in settings section using Library keyword. I have answered this question in detail with all the steps mention in this link.
Create a python file(comparejsons.py) with the above code in it
Keep the above python file in PYTHONPATH
Use Library comparejsons.py under settings section in your robot file
APPROACH#1
You should create a custom keyword which makes use of the below library and then compare the 2 jsons.
You can make use of "robotframework-jsonvalidator" module
Sample code below,
*** Settings ***
Library JsonValidator
Library OperatingSystem
*** Test Cases ***
Check Element
${json_example}= OperatingSystem.Get File ${CURDIR}${/}json_example.json
Element should exist ${json_example} .author:contains("Evelyn Waugh")
APPROACH#2
After converting the JSON to a dictionary you can just make use of the Built-in keyword , here , values=True is imortant.
Dictionaries Should Be Equal<<TAB>>dict1<<TAB>>dict2<<TAB>>values=True

Related

Reading the Json string which is put together in one field

I have a Json pattern string in a text file, I have to pharse the below string like below and put it in to a external file.
Please let me know how this can be handled with Informatica Powercenter or Unix or Python?
{"CONTACTID":"3b2a25b2","ANI":"+16146748702","DNIS":"+18006081123","START_TIME":"01/22/2023 03:31:42","MODULE":[{"Name":"MainIVR","Time":"01/22/2023 03:31:42",Dialog":[{"name":"offer_Spanish","dialogeresult":"(|raw:7|R|7|1.0|nm=0|ni=0|2023/22/21 03:02:01)"}],"backend":[{"Time":"01/22/2023)"}],"END_STATE":"XC"}
In The above sample string the special charcters should be removed and the values should be assigned to the corresponding columns like below 2 o/p formats
Output:
CONTACTID, ANI, DNIS, START_TIME, MODULE, Time,Dialog,dialogeresult,END_STATE
3b2a25b2,+16146748702 +18006081123 01/22/2023 03:31:42,Name:MainIVR,
or
Output:
CONTACTID : 3b2a25b2
ANI:16146748702
DNI :+18006081123
I tried this to read thru Informatica powercenter and using the expression tranformations but nothing worked and tried with Python too.
For a start, your JSON is invalid. The opening double quotes for Dialog are missing and it's not properly closed - MODULE array is not closed and root is not closed. Here's the fixed JSON:
{"CONTACTID":"3b2a25b2","ANI":"+16146748702","DNIS":"+18006081123","START_TIME":"01/22/2023 03:31:42","MODULE":[{"Name":"MainIVR","Time":"01/22/2023 03:31:42","Dialog":[{"name":"offer_Spanish","dialogeresult":"(|raw:7|R|7|1.0|nm=0|ni=0|2023/22/21 03:02:01)"}],"backend":[{"Time":"01/22/2023)"}],"END_STATE":"XC"}]}
Use some JSON validation tool, like this one - it helps a lot.
Next, here's some starter code you may use to achieve the required result:
import json
# some JSON:
x = '{"CONTACTID":"3b2a25b2","ANI":"+16146748702","DNIS":"+18006081123","START_TIME":"01/22/2023 03:31:42","MODULE":[{"Name":"MainIVR","Time":"01/22/2023 03:31:42","Dialog":[{"name":"offer_Spanish","dialogeresult":"(|raw:7|R|7|1.0|nm=0|ni=0|2023/22/21 03:02:01)"}],"backend":[{"Time":"01/22/2023)"}],"END_STATE":"XC"}]}'
# parse x:
y = json.loads(x)
# the result is a Python dictionary:
print(y.keys())
You may test it on Replit
Finally regarding Informatica Powercenter - it is a terrible choice for complex string processing. You would need a Hierarchy Parser Transformation. Long story short: it's very tedious, but possible. I would highly recommend picking up a differen approach, if this is not a regular data loading process you will need to build.

How to parse lua table object into json?

I was wondering if there was a way to parse a lua table into an javascript object, without using any libraries i.e require("json") haven't seen one yet, but if someone knows how please answer
If you want to know how to parse Lua tables to JSON strings take a look into the source code of any of the many JSON libraries available for Lua.
http://lua-users.org/wiki/JsonModules
For example:
https://github.com/rxi/json.lua/blob/master/json.lua
or
https://github.com/LuaDist/dkjson/blob/master/dkjson.lua
If you do not want to use any library and want to do it with pure Lua code the most convenient way for me is to use table.concat function:
local result
for key, value in ipairs(tableWithData) do
-- prepare json key-value pairs and save them in separate table
table.insert(result, string.format("\"%s\":%s", key, value))
end
-- get simple json string
result = "{" .. table.concat(result, ",") .. "}"
If your table has nested tables you can do this recursively.
The are a lot of pure-Lua JSON libraries.
Even me have one.
How to include pure-Lua module into your script without using require():
Download the Lua JSON module (for example, go to my json.lua, right-click on Raw and select Save Link as in context menu)
Delete the last line return json from this file
Insert the whole file at the beginning of your script
Now you can use local json_as_string = json.encode(your_Lua_table) in your script.

passing variable to json file while matching response in karate

I'm validating my response from a GET call through a .json file
match response == read('match_response.json')
Now I want to reuse this file for various other features as only one field in the .json varies. Let's say this param in the json file is "varyingField"
I'm trying to pass this field every time I am matching the response but not able to
def varyingField = 'VARIATION1'
match response == read('match_response.json') {'varyingField' : '#(varyingField)'}}
In the json file I have
"varyingField": "#(varyingField)"
You are trying to use an argument to read for a JSON file ? Sorry such a thing is not supported in Karate, please read the docs.
Use this pattern:
create a JSON file that has all your "happy path" values set
use the read() syntax to load the file (which means this is re-usable across multiple tests)
use the set keyword to update only the field for your scenario or negative test
For more details, refer this answer: https://stackoverflow.com/a/51896522/143475

Parsing large JSON file with Scala and JSON4S

I'm working with Scala in IntelliJ IDEA 15 and trying to parse a large twitter record json file and count the total number of hashtags. I am very new to Scala and the idea of functional programming. Each line in the json file is a json object (representing a tweet). Each line in the file starts like so:
{"in_reply_to_status_id":null,"text":"To my followers sorry..
{"in_reply_to_status_id":null,"text":"#victory","in_reply_to_screen_name"..
{"in_reply_to_status_id":null,"text":"I'm so full I can't move"..
I am most interested in a property called "entities" which contains a property called "hastags" with a list of hashtags. Here is an example:
"entities":{"hashtags":[{"text":"thewayiseeit","indices":[0,13]}],"user_mentions":[],"urls":[]},
I've browsed the various scala frameworks for parsing json and have decided to use json4s. I have the following code in my Scala script.
import org.json4s.native.JsonMethods._
var json: String = ""
for (line <- io.Source.fromFile("twitter38.json").getLines) json += line
val data = parse(json)
My logic here is that I am trying to read each line from twitter38.json into a string and then parse the entire string with parse(). The parse function is throwing an error claiming:
"Type mismatch, expected: Nothing, found:String."
I have seen examples that use parse() on strings that hold json objects such as
val jsontest =
"""{
|"name" : "bob",
|"age" : "50",
|"gender" : "male"
|}
""".stripMargin
val data = parse(jsontest)
but I have received the same error. I am coming from an object oriented programming background, is there something fundamentally wrong with the way I am approaching this problem?
You have most likely incorrectly imported dependencies to your Intellij project or modules into your file. Make sure you have the following lines imported:
import org.json4s.native.JsonMethods._
Even if you correctly import this module, parse(String: json) will not work for you, because you have incorrectly formed a json. Your json String will look like this:
"""{"in_reply_...":"someValue1"}{"in_reply_...":"someValues2"}"""
but should look as follows to be a valid json that can be parsed:
"""{{"in_reply_...":"someValue1"},{"in_reply_...":"someValues2"}}"""
i.e. you need starting and ending brackets for the json, and a comma between each line of tweets. Please read the json4s documenation for more information.
Although being almost 6 years old, I think this question deserves another try.
JSON format has a few misunderstandings in people's minds, especially how they are stored and how they are read back.
JSON documents, are stored as either a single object having all the other fields, or an array of multiple object possibly in same format. this second part is important because arrays in almost every programming language are defined by angle brackets and values separated by commas (note here I used a person object as my single value):
[
{"name":"John","surname":"Doe"},
{"name":"Jane","surname":"Doe"}
]
also note that everything except brackets, numbers and booleans are enclosed in quotes when written into file.
however, there is another use that is not official but preferred to transfer datasets easily where every object, or document as in nosql/mongo language, are stored in a new line like this:
{"name":"John","surname":"Doe"}
{"name":"Jane","surname":"Doe"}
so for the question, OP has a document written in this second form, but tries an algorithm written to read the first form. following code has few simple changes to achieve this, and the user must read the file knowing that:
var json: String = "["
for (line <- io.Source.fromFile("twitter38.json").getLines) json += line + ","
json=json.splitAt(json.length()-1)._1
json+= "]"
val data = parse(json)
PS: although #sbrannon, has the correct idea, the example he/she gave has mistakenly curly braces instead of angle brackets to surround the data.
EDIT: I have added json=json.splitAt(json.length()-1)._1 because the code above ends with a trailing comma which will cause parse error per the JSON format definition.

Verify whole json response in jmeter by value or sort Json

I'm not using JMeter too often, and I've run into very specific issue.
My REST response is always "the same", but nodes are not in the same order due to various reasons. As well, I can't put here whole response due to sensitive data, but let's use these dummy one:
First time response might be:
{
"properties":{
"prop1":false,
"prop2":false,
"prop3":165,
"prop4":"Audi",
"prop5":true,
"prop6":true,
"prop7":false,
"prop8":"1",
"prop9":"2.0",
"prop10":0
}
}
Then other time it might be like this:
{
"properties":{
"prop2":false,
"prop1":false,
"prop10":0,
"prop3":165,
"prop7":false,
"prop5":true,
"prop6":true,
"prop8":"1",
"prop9":"2.0",
"prop4":"Audi"
}
}
As you can see, the content it self is the same, but order of nodes it's not. I have 160+ nodes and thousand of possible response orders.
Is there an easy way to compare two JSON responses comparing matching key - values, or at least to sort the response, and then compare it with sorted one in assertion patterns?
I'm not using any plugins, just basic Apache JMeter.
Thanks
I've checked using Jython, you need to download the Jython Library and save to your jmeter lib directory.
I've checked 2 JSONs with Sampler1 and Sampler2, on Sampler1 I've add a BeanShell PostProcessor with this code:
vars.put("jsonSampler1",prev.getResponseDataAsString());
On Sampler2 I've add a BSF Assertion, specifying jython as the language and with the following code:
import json
jsonSampler1 = vars.get("jsonSampler1")
jsonSampler2 = prev.getResponseDataAsString()
objectSampler1 = json.loads(jsonSampler1)
objectSampler2 = json.loads(jsonSampler2)
if ( objectSampler1 != objectSampler2 ):
AssertionResult.setFailure(True)
AssertionResult.setFailureMessage("JSON data didn't match")
Yoy can find the whole jmx in this GistHub
You will most probably have to do this with a JSR223 Assertion and Groovy.
http://jmeter.apache.org/usermanual/component_reference.html#JSR223_Assertion
http://docs.groovy-lang.org/latest/html/api/groovy/json/JsonSlurper.html
Note that if you know Python, you might look at using Jython + JSR223.
I would just set up 10 jp#gc - JSON Path Assertions. Documentation for figuring out JSON Path format is here and you can test how it would work here.
For your example you would the assertion (Add > Assertion > jp#gc - JSON Path Assertions), then to test the prop 1 put:
$.properties.prop1
in the JSON Path field, click the Validate Against Expected Value checkbox, and put
false
in the expected value field. Repeat those steps for the other 9 changing the last part of the path to each key and the value you expected back in the expected value field.
This extractor is jmeter add on found here.