How do I delete JSON object properties dynamically? I tried this:
* def delKey =
"""
function(json, key) {
delete json[key];
return json;
}
"""
* def aJson = { row: null, age: 35 , city: 'na'}
* print "Before: "
* print aJson
* def called = delKey(aJson, 'age')
* print "After: "
* print aJson
The result:
I think you have not seen the remove and set keywords. Here is the right approach. Also note how the print statement supports a comma-delimited style so that it will pretty-print:
* def aJson = { row: null, age: 35 , city: 'na' }
* print 'Before: ', aJson
* remove aJson.age
* print 'After: ', aJson
If you need to remove keys dynamically, the JS API karate.remove(name, path) can be used. Refer to the docs !
Related
The goal is to do soft assertion on each JSON field.
* def KAFKA_TOPIC = "topic1"
* def kafkaExpected = {field1:"value1",field2:"value2",field3:"value3"}
* def kafkaActual = {"topic1":[{field1:"value1",field2:"x",field3:"y"}]}
* configure continueOnStepFailure = { enabled: true, continueAfter: false, keywords: ['match'] }
* match (kafkaActual[KAFKA_TOPIC]) == ['#(kafkaExpected)'] <-- do we have one-liner like this to do soft assertions on all fields?
* configure continueOnStepFailure = false
Output:
$[0].field2 | not equal (STRING:STRING)
'x'
'value2'
Instead of doing it 1 by 1.
* match (kafkaActual[KAFKA_TOPIC])[0].field1 == kafkaExpected.field1
* match (kafkaActual[KAFKA_TOPIC])[0].field2 == kafkaExpected.field2
* match (kafkaActual[KAFKA_TOPIC])[0].field3 == kafkaExpected.field3
Output:
match failed: EQUALS
$ | not equal (STRING:STRING)
'x'
'value2'
match failed: EQUALS
$ | not equal (STRING:STRING)
'y'
'value3'
And whats weird is that on terminal logs it only printed one assertion, either on both approach.
$ | not equal (STRING:STRING)
'y'
'value3'
Trying to use Karate.forEach but seems like not the right path.
Found a solution from this link provided by Peter. I just need to transform the JSON to list of key, value format and use it as data source.
From:
{field1:"value1",field2:"value2",field3:"value3"}
Transformed To:
[{key:"field1",value:"value1"},{key:"field2",value:"value2"},{key:"field3",value:"value3"}]
Function used and usage:
* def input = INPUT
* def func =
"""
function(obj){
var output = [];
for (var i in obj) {
output.push({key: i, value: obj[i]});
}
return output
}
"""
* json kafkaAttributes = func(input)
* configure continueOnStepFailure = { enabled: true, continueAfter: false, keywords: ['match'] }
* karate.call('kafka.feature#validateFieldsAndValues',kafkaAttributes)
* configure continueOnStepFailure = false
#validateFieldsAndValues
Scenario:
* match (response[KAFKA_TOPIC][0][key]) contains value
When i am passing the value of a string json filter is working fine. But when I am passing embedded expression in the JSONPATH it is not replacing actual value.
Given url appServer +'/integration/rest/user'+'?page=0'+'&pageSize=10'+'&fieldList=first_name,last_name,id,username,last_login,active,date_created'+'&filter=user_type%20equals%20%27P%27%20'+'&getTotalRecordCount=true'
And header X-CSRF-TOKEN = csrfToken
* cookie JSESSIONID = jsessionid
* print routevalue
* cookie route = routevalue
* string searchUser = 'anupama'
* callonce sleep 10
Given request ' '
When method get
Then status 200
* def usernames = get response.integration.serviceData.record[*].username
* print usernames
* print searchUser
* def userNode = get[0] response.integration.serviceData.record[?(#.username== '#(searchUser)')]
* print userNode
Embedded expressions are only for JSONPath and XML: https://github.com/intuit/karate#embedded-expressions
Please use the karate API for dynamic JsonPath: https://github.com/intuit/karate#jsonpath-filters
* def userNode = karate.jsonPath(response, "$.integration.serviceData.record[?(#.username=='" + searchUser + "')]")
I am trying to generate auto json paths from given json structure but stuck in the programatic part. Can someone please help out with the idea to take it further?
Below is the code so far i have achieved.
def iterate_dict(dict_data, key, tmp_key):
for k, v in dict_data.items():
key = key + tmp_key + '.' + k
key = key.replace('$$', '$')
if type(v) is dict:
tmp_key = key
key = '$'
iterate_dict(v, key, tmp_key)
elif type(v) is list:
str_encountered = False
for i in v:
if type(i) is str:
str_encountered = True
tmp_key = key
break
tmp_key = key
key = '$'
iterate_dict(i, key, tmp_key)
if str_encountered:
print(key, v)
if tmp_key is not None:
tmp_key = str(tmp_key)[:-str(k).__len__() - 1]
key = '$'
else:
print(key, v)
key = '$'
import json
iterate_dict_new(dict(json.loads(d_data)), '$', '')
consider the below json structure
{
"id": "1",
"categories": [
{
"name": "author",
"book": "fiction",
"leaders": [
{
"ref": ["wiki", "google"],
"athlete": {
"$ref": "some data"
},
"data": {
"$data": "some other data"
}
}
]
},
{
"name": "dummy name"
}
]
}
Expected output out of python script:
$id = 1
$categories[0].name = author
$categories[0].book = fiction
$categories[0].leaders[0].ref[0] = wiki
$categories[0].leaders[0].ref[1] = google
$categories[0].leaders[0].athlete.$ref = some data
$categories[0].leaders[0].data.$data = some other data
$categories[1].name = dummy name
Current output with above python script:
$.id 1
$$.categories.name author
$$.categories.book fiction
$$$.categories.leaders.ref ["wiki", "google"]
$$$$$.categories.leaders.athlete.$ref some data
$$$$$$.categories.leaders.athlete.data.$data some other data
$$.name dummy name
The following recursive function is similar to yours, but instead of just displaying a dictionary, it can also take a list. This means that if you passed in a dictionary where one of the values was a nested list, then the output would still be correct (printing things like dict.key[3][4] = element).
def disp_paths(it, p='$'):
for k, v in (it.items() if type(it) is dict else enumerate(it)):
if type(v) is dict:
disp_paths(v, '{}.{}'.format(p, k))
elif type(v) is list:
for i, e in enumerate(v):
if type(e) is dict or type(e) is list:
disp_paths(e, '{}.{}[{}]'.format(p, k, i))
else:
print('{}.{}[{}] = {}'.format(p, k, i, e))
else:
f = '{}.{} = {}' if type(it) is dict else '{}[{}] = {}'
print(f.format(p, k, v))
which, when ran with your dictionary (disp_paths(d)), gives the expected output of:
$.categories[0].leaders[0].athlete.$ref = some data
$.categories[0].leaders[0].data.$data = some other data
$.categories[0].leaders[0].ref[0] = wiki
$.categories[0].leaders[0].ref[1] = google
$.categories[0].book = fiction
$.categories[0].name = author
$.categories[1].name = dummy name
$.id = 1
Note that this is unfortunately not ordered, but that is unavoidable as dictionaries have no inherent order (they are just sets of key:value pairs)
If you need help understanding my modifications, just drop a comment!
I have a string as follows,
s= "query : {'$and': [{'$or': [{'Component': 'pfr'}, {'Component': 'ng-pfr'}, {'Component': 'common-flow-table'}, {'Component': 'media-mon'}]}, {'Submitted-on': {'$gte': datetime.datetime(2016, 2, 21, 0, 0)}}, {'Submitted-on': {'$lte': datetime.datetime(2016, 2, 28, 0, 0)}}]}
" which is a MongoDB query stored in a string.How to convert it into a Dict or JSON format in Python
Your format is not standard, so you need a hack to get it.
import json
s = " query : {'names' :['abc','xyz'],'location':'India'}"
key, value = s.strip().split(':', 1)
r = value.replace("'", '"')
data = {
key: json.loads(r)
}
From your comment: the datetime gives problems. Then I present to you the hack of hacks: the eval function.
import datetime
import json
s = " query : {'names' :['abc','xyz'],'location':'India'}"
key, value = s.strip().split(':', 1)
# we can leave out the replacing, single quotes is fine for eval
data = {
key: eval(value)
}
NB eval -especially on unsanitized input- is very unsafe.
NB: hacks will be broken, in the first case for example because a value or key contains a quote character.
{
"event_type": "ITEM_PREVIEW",
"event_id": "67521d60cbb5f4dedef901d5e82f394ed122662d",
"created_at": "2015-10-21T14:12:46-07:00"
}
I have this json which is being read as a list; how do I
convert it to a json
or
convert it to a dict such as event_type = key and ITEM_PREVIEW = value
I tried converting in to a string and use json.Encoder
I also tried this the first function gets events and saves it to a file the I want the second one to be able to parse the information
def events():
for event in client.events().generate_events_with_long_polling():
print(event)
ev = open('events.txt', 'a')
json.dump(event, ev)
ev.write('\n')
ev.close()
return ev
#events()
def trigger():
entries = open('events.txt', 'rU')
print('\n', type(entries))
dictss = entries.readlines()
print('\n', type(dictss), '\n', len(dictss))
for q in dictss:
print(q)
w = dict([x.strip().split(":") for x in dictss if " " in x])
print(w)
trigger()