Is it possible to do nested search in jsonpath-ng? - json

Source "mapping.json":
{
"result": {
"src_color": "test_rule_2"
},
"rules": {
"color_degree": {
"test_rule_1": {
"color": 1
},
"test_rule_2": {
"color": 2
}
}
}
}
So it works perfectly:
with open("mapping.json", 'r') as json_file:
mapping = json.load(json_file)
expression = parse('$.rules.color_degree.test_rule_2.color')
match = expression.find(mapping)
if match:
pprint(match[0].value)
but in the path "test_rule_2" I need to replace with the value from result->src_color
How to properly describe something like this:
expression = parse('$.rules.color_degree.($.result.src_color.value).color')

If I understand your question correctly, it can be done, but you need two steps:
#first: get the variable:
src_expression = parse('$.result.src_color')
src_match = src_expression.find(mapping)
#second: get the target
expression = parse(f'$.rules.color_degree.{src_match[0].value}.color')
match = expression.find(mapping)
if match:
print(match[0].value)
Output is 2.
EDIT:
I don't know why someone would want to do it in one step, but it's possible:
parse(f'$.rules.color_degree.{parse("$.result.src_color").find(mapping)[0].value}.color').find(mapping)[0].value
Same output.

Related

Extracting one specific line from parsed JSON string

Trying to pull first value from a parsed JSON string using the JsonConverter library.
What I currently have is:
result = objHTTP.responseText
Set parsedResult = JsonConverter.ParseJson(result)
i = 3
For Each Item In parsedResult("From")
wsSheet0.Cells(i, 12) = parsedResult("From")(Item)("Price")
i = i + 1
Next
With parsedResult("From")
wsSheet0.Cells(11, 12) = parsedResult("From")("Chocolate")("Price")("AsAtDate")
End With
The last line of this gets a type mismatch error, so I'm still trying to figure out how to just pull that one line item.
For the sake of clarity, the parsed JSON string looks like:
{
"From":{
"Chocolate":{
"Price":1.0,
"AsAtDate":"2018-05-04T00:00:00"
},
"Lime":{
"Price":1.35415115,
"AsAtDate":"2018-05-04T00:00:00"
},
"Strawberry":{
"Price":1.19517151,
"AsAtDate":"2018-05-04T00:00:00"
},
"Vanilla":{
"Price":0.77522986,
"AsAtDate":"2018-05-04T00:00:00"
},
"Blueberry":{
"Price":1.00084071,
"AsAtDate":"2018-05-04T00:00:00"
},
"Lemon":{
"Price":0.75030012,
"AsAtDate":"2018-05-04T00:00:00"
}
},
"To":"Chocolate",
"RequestedDate":"2018-05-22T08:26:16"
}
Use
parsedResult("From")("Chocolate")("AsAtDate")
Or more generally to get all:
parsedResult("From")(item)("AsAtDate")

How to validate Sub-Sets of JSON Keys using match contains when there are nested JSON's in the response

From a response, I extracted a subset like this.
{
"base": {
"first": {
"code": "1",
"description": "Its First"
},
"second": {
"code": "2",
"description": "Its Second"
},
"default": {
"last": {
"code": "last",
"description": "No"
}
}
}
}
If I need to do a single validation using And match X contains to check
Inside first the Code is 1
Inside default-last the code is last?
Instead of using json path for every validation, I am trying to extract a specific portion and validate it. If there is no nested json paths, I can do it very easily using And match X contains, however when there are nested jsons, I am not able to do it.
Does this work for you:
* def first = get[0] response..first
* match first.code == '1'
* def last = get[0] response..default.last
* match last.code == 'last'
Edit: ok looks like you want to condense into one line as far as possible, more importantly to be able to do contains in nested nodes. Personally, I find this sometimes to be not worth the trouble, but here goes.
Refer also to these short-cuts: https://github.com/intuit/karate#contains-short-cuts
* def first = { code: "1" }
* match response.base.first contains first
* match response.base contains { first: '#(^first)' }
* def last = { code: 'last' }
* match response.base contains { first: '#(^first)', default: { last: '#(^last)' } }
Mhmm, My question is slightly different I think.
For example if I directly point to the first using a json path and save it to a variable savedResponse, I can do this validation
And match savedResponse contains {code: "1"}
If there were 10 Key value combinations under first and if I need to validate 6 of those, I can use the same json path and I can easily do it using match contains
Similiar way if I save the above response to a variable savedResponse, how I can validate mutliple things using match contains, in this. The below statement will not work anyway.
And match savedResponse contains {first:{code:"1"}, last:{code:"last"}}
However if I modify something will it work?

How to check a value matches with another correpsonding value in a json response

What is the most dynamic way of checking each instance of a json response value matches another json response value within a script assertion?
What I mean is lets say I have the following response below:
{
"xxx": [{
"roomInformation": [{
"xxx": xxx
}],
"totalPrice": xxx
},
{
"roomInformation": [{
xxx: xxx
}],
"totalPrice": xxx
}
]
}
I want to check that the first room price to match with the first totalPrice and the second roomPrice to match with the second totalPrice. It has to be dynamic as I may get many different instances of this so I can't simply just look through the json with [0] and [1]. Virtually check each roomPrice matches with its corresponding totalPrice.
Thanks
So given the Json as a variable:
def jsonTxt = '''{
"hotels": [{
"roomInformation": [{
"roomPrice": 618.4
}],
"totalPrice": 618.4
},
{
"roomInformation": [{
"roomPrice": 679.79
}],
"totalPrice": 679.79
}
]
}'''
We can then use the following script:
import groovy.json.*
new JsonSlurper().parseText(jsonTxt).hotels.each { hotel ->
assert hotel.roomInformation.roomPrice.sum() == hotel.totalPrice
}
As you can see, I'm using sum to add all the roomInformation.roomPrice values together. In your example, you only have one price, so this will be fine.. And it will also cover the case where you have multiple rooms adding up to make the total
Here is the script assertion to check each roomPrice is matching or not with totalPrice.
EDIT: based on OP's full response provided here
Script Assertion:
//Check if the response is not empty
assert context.response, "Response is empty or null"
def json = new groovy.json.JsonSlurper().parseText(context.response)
def sb = new StringBuffer()
json.regions.each { region ->
region.hotels.each { hotel ->
(hotel?.totalPrice == hotel?.roomInformation[0]?.roomPrice) ?: sb.append("Room price ${hotel?.roomInformation[0]?.roomPrice} is not matching with total price ${hotel.totalPrice}")
}
}
if (sb.toString()) {
throw new Error(sb.toString())
} else { log.info 'Prices match' }

How to send multiple documents using RMongo

I am following the conventions from http://docs.mongodb.org/manual/reference/method/db.collection.insert/
to send a batch of multiple documents in one call of RMongo::dbInsertDocument.
data=data.frame(A=c(1,2),B=c(3,4))
L=lapply(split(data,rownames(data)),as.list)
names(L)=NULL
dataJSON = toJSON(L)
cat(dataJSON)
which gives the following result:
[
{
"A":1,
"B":3
},
{
"A":2,
"B":4
}
]
Then
dbInsertDocument(rmongo.object=myRmongo.object, collection=myCollection, doc=dataJSON)
returns the following error:
Error in ls(envir = envir, all.names = private) :
invalid 'envir' argument
Note that if I replace
L = L[[1]
Then
cat(dataJSON)
gives the following result:
{
"A":1,
"B":3
}
and the same call to dbInsertDocument works with no error (and the data is indeed sent to the database)
Has anyone figured this out? I would really like a better way to do this, but for now am just looping over the list (not ideal)
data=data.frame(A=c(1,2),B=c(3,4))
L=lapply(split(data,rownames(data)),as.list)
names(L)=NULL
for (i in 1:NROW(L)) {
dataJSON = toJSON(L[[i]])
output <- dbInsertDocument(mongo, "test_data7", dataJSON)
}

simple json parsing with asp Xtreme

Just confused with one little thing.
I am currently getting { "data": [ { "response": "true" } ] } with the following code.
But I simple want to get { "response": "true" }.
I tried every way I can but I kept failing.
I will appreciate a lot if you can help me with it.
Set Dataset = JSON.parse("{ ""data"": [] }")
Set Record = JSON.parse("{}")
Record.set "response", "true"
Dataset.data.push(Record)
Set Record = nothing
Data = JSON.stringify(Dataset, null, 2)
Set Record = JSON.parse("{}")
Record.set "response", "true"
Data = JSON.stringify(Record, null, 2)
I assume that JSONObject.data.push adds the record to an unnamed array.