How to reference parent names in JSON response (with Groovy) - groovy

I have the following JSON response in SoapUI
{
"formatted": {
"line1": "14/8 QUAY STREET",
"line2": "14/8 QUAY STREET"
},
"structure": {
"level": null
},
"location": {
"nzX": 1758749.75300025
},
"references": {
"aid": "A1003467096"
}
}
I want the following as the output
formatted, structure, location and references.
I am using Json slurper but i am not able to get all the parent element names.
How do i do it using JSON slurper in groovy.

Assuming the JSON is in a string s, consider the following which illustrates getting the top level keys:
import groovy.json.*
def json = new JsonSlurper().parseText(s)
def parentNames = json.keySet()
parentNames.each { println it }

Related

Parsing JSON from POST request using Python and FastAPI

I'm trying to parse a JSON that came from a POST request from user to my API made with FastAPI. I have a nested JSON that can receive multiple values and my problem is: How can I parse it and get the values from this nested JSON?
The JSON is like this:
{
"recipe": [
{
"ingredient": "rice",
"quantity": 1.5
},
{
"ingredient": "carrot",
"quantity": 1.8
},
{
"ingredient": "beans",
"quantity": 1.8
}
]
}
I must grab the all values from the list recipe separated, as I have a database with this ingredient and will query all of this and do some calculates with the quantity given from user. But I don't even know how I can parse this JSON from the POST request.
I already have a 2 classes with Pydantic validating this values like:
class Ingredientes(BaseModel):
ingredient: str
quantity: float
class Receita(BaseModel):
receita: List[Ingredientes] = []
Edit 1: I tried to include it in my function that recieve this POST request and didn't work like:
#app.post('/calcul', status_code=200)
def calculate_table(receita: Receita):
receipe = receita["receita"]
for ingredient in receipe:
return f'{ingredient["ingredient"]}: {ingredient["quantity"]}'
Edit 2: Fixed the issue with the code bellow(Thanks MatsLindh):
#app.post('/calcul', status_code=200)
def calculate_table(receita: Receita):
receipe = receita.receita
for ingredient in receipe:
return f'{ingredient.ingrediente}: {ingredient.quantidade}'
To parse a JSON-formatted string (from the POST request, for example) into a dictionary, use the loads function from the json module, like this:
import json
s = """{
"recipe": [
{
"ingredient": "rice",
"quantity": 1.5
},
{
"ingredient": "carrot",
"quantity": 1.8
},
{
"ingredient": "beans",
"quantity": 1.8
}
]
}
"""
recipe = json.loads(s)["recipe"]
for ingredient in recipe:
print(f"{ingredient['ingredient']}: {ingredient['quantity']}")

How to use Pydantic base schema to n number of child schema

I'm new to pydantic, I want to define pydantic schema and fields for the below python dictionary which in the form of JSONAPI standard
{
"data": {
"type": "string",
"attributes":{
"title": "string",
"name": "string"
}
}
I managed to achieve this by defining multiple schemas like below,
class Child2(BaseModel):
title: str
name: str
class Child1(BaseModel):
type: str
attributes: Child2
class BaseParent(BaseModel):
data: Child1
But, I will be having multiple json request with the same json API structure as below,
example 1 {
"data": {
"type": "string",
"attributes":{
"source": "001",
"status": "New"
}
}
example 2 {
"data": {
"type": "string",
"attributes":{
"id": "001"
}
}
If you look into the above python dictionary, Values only under the attributes object are different. So, is there any way that I can define a parent marshmallow scheme for { "data": { "type": "string", "attributes":{ } } } and use that parent schema for all child schema's.
I found an answer finally, Hope this will help someone.
Pydantic 'create_model' concept will help to resolve this kind of requirement by passing child schema as one of the field values to create_model.
class Child(BaseModel):
title: str
name: str
class BaseParent(BaseModel):
data: create_model('BaseParent', type=(str, ...), attributes=(Child, ...))
And this will frame a BaseParent schema structure as below,
data=BaseParent(type='id', attributes=Child2(title='test002', name='Test'))

Generate json body using groovy in jmeter having array inside an array

I'm trying to generate JSON body dynamically using values in csv file. For this i'm making use of JSR223 PreProcessor with groovy script.
I'm expecting the below format to be generate when i run the groovy script
{
"transactionId": "100",
"lineItems": [{
"lineItemNo": "1",
"cardInfo": {
"cardNumber": "3456"
}
},
{
"lineItemNo": "2",
"cardInfo": {
"cardNumber": "45698"
}
}
]
}
but when i execute script i'm getting below format
POST data:
{
"transactionId": "100",
"lineItems": [
{
"lineItemNo": "1",
"Cardinfo": [
9255000012794606,
9255000012794645
]
},
{
"lineItemNo": "1",
"Cardinfo": [
9255000012794606,
9255000012794645
]
}
]
}
Script to generate json body
File csvFile = new File("D:\\Project Related Docs\\Jmeter\\apache-jmeter-5.0\\bin\\Map_Performance\\Map_New_Auto_jmx\\2Cards.csv")
def cards = csvFile.readLines()
List<String> cardnumbmer = new ArrayList<>()
def counter = 1
cards.eachWithIndex{line,idx->cardnumbmer.add(line)}
log.info("size of csv = "+cardnumbmer.size())
log.info("File conents = "+cardnumbmer[0])
//build the json body
def ids = new groovy.json.JsonSlurper().parseText(cardnumbmer.toString())
log.info("cardnumbmer to string = "+cardnumbmer.toString())
def builder = new groovy.json.JsonBuilder()
builder([
transactionId:"100",
lineItems:ids.collect{[lineItemNo:"1",Cardinfo: ids.collect{carnumber: it}]}
])
//sampler.getArguments().removeAllArguments()
sampler.addNonEncodedArgument('',builder.toPrettyString(),'')
sampler.setPostBodyRaw(true);
--CSV FILE have cardnumbers listed in row-wise look like below
9255000012794606
9255000012794645
Request to help me to know how to fix this issue.
ids.collect{carnumber: it} is basically ids. Be explicit about returning the map: ids.collect{ [carnumber: it] }
Below code resolved the problem
//build the json body
def ids = new groovy.json.JsonSlurper().parseText(cardnumbmer.toString())
log.info("cardnumbmer to string = "+cardnumbmer.toString())
def builder = new groovy.json.JsonBuilder()
def count = 1
builder([
transactionId:"100",
//lineItems:ids.collect{[lineItemNo:"1",Cardinfo: count.collect{[carnumber: it]}]}
lineItems:ids.collect{[lineItemNo:count++,Cardinfo: [Cardnumber:it]]}
])
//sampler.getArguments().removeAllArguments()
sampler.addNonEncodedArgument('',builder.toPrettyString(),'')
sampler.setPostBodyRaw(true);

How to iterate through each property element in API response in Katalon studio?

I'm writing test script in katalon studio to verify response body of the API.My response body is of format:
{
"status": "Success",
"correlationCode": "1234-5678",
"type": {
"id": 51247,
"name": "Student",
},
"data": {
"name": "Sara Nieves",
"gender": "Female",
"dob": "1995-08-06",
"libraryCard": {
"id": "11178",
"type": "Seniors"
},
"qualifications": [
{
"id": "45650986546",
"name": "Graduate Certificate in Environmental Engineering Management"
}
]
}
}
I want to verify that none of the elements return 'null' value. Since, the elements returned for the API response are not static(meaning name, gender etc might not get returned every time) therefore, i can't use something like "data.name" to verify if it has null value. So, i want a generic way to loop through each and every attribute returned and check if its value is returned as null or not.
Any help will be much appreciated. Thanks!
You have the error message:
groovy.lang.MissingMethodException: No signature of method: WSVerification1569811424284$_run_closure1.doCall() is applicable for argument types: (com.kms.katalon.core.testobject.ResponseObject) values: [200 1 KB] 22572.groovy:21)
I assume your response object type: com.kms.katalon.core.testobject.ResponseObject
The code to parse response as json and validate it:
import groovy.json.JsonSlurper
/**
* the recursive method to validate that json object does not have null values
* #param obj - the parsed json object (sequence of maps and lists)
* #param path - a variable to know where the error occurred in json data.
*/
void assertNoNullValue(Object obj, String path='ROOT'){
//the main assertion
assert obj!=null : "value in json could not be null: $path"
if(obj instanceof Map){
//iterate each key-value in map and validate the value recursively
obj.each{k,v-> assertNoNullValue(v,path+".$k") }
} else if(obj instanceof List){
//iterate each value in list and validate the value recursively
obj.eachWithIndex{v,i-> assertNoNullValue(v,path+"[$i]") }
}
}
def response = ...
assert response.isJsonContentType()
def responseText = response.getResponseText()
//parse body
def data = new JsonSlurper().parseText(responseText)
assertNoNullValue(data)
This solution is not as precise as the one suggested by #dagget, but it is a quick check:
def response = '''
{
"status": "Success",
"correlationCode": "1234-5678",
"type": {
"id": 51247,
"name": "Student",
},
"data": {
"name": "Sara Nieves",
"gender": "femmina",
"dob": "1995-08-06",
"libraryCard": {
"id": "11178",
"type": "Seniors"
},
"qualifications": [
{
"id": "45650986546",
"name": "Graduate Certificate in Environmental Engineering Management"
}
]
}
}
'''
assert !response.contains("null")

How to get data from json format using groovy?

i have a request in soapui which returns a json response.
i'm using groovy to retrieve the content of the response.
response :
<item><response>{
"timestamp": "2016-04-01T16:40:34",
"data": [
{
"deleted_at": null,
"userid": "b6d66002-8da4-4c03-928c-46871f084fb8",
"updated_by": null,
"created_at": "2016-03-01T16:40:34",
"updated_at": "2016-03-01T16:40:34",
"created_by": null,
"value": "hBeO",
"setting": "test",
"name": "test2"
}
],
"success": true
}</response></item>
From this response i want to retrieve each node like:
deleted_at
created_at
so i use this groovy
import groovy.json.JsonSlurper
def response = context.expand( '${set_settings#Response#declare namespace ns1=\'https://wato.io/ns/20160131\'; //ns1:set_settings_resp[1]/ns1:item[1]/ns1:response[1]}' )
def slurper = new JsonSlurper()
def result = slurper.parseText(response)
testRunner.testCase.setPropertyValue("user_id", result.data.userid)
and i receive this error message:
groovy.lang.MissingMethodException: No signature of method: com.eviware.soapui.impl.wsdl.WsdlTestCasePro.setPropertyValue() is applicable for argument types: (java.lang.String, java.util.ArrayList) values: [userid, [b6df6662-8da4-4c03-928c-46871f084fb8]] Possible solutions: setPropertyValue(java.lang.String, java.lang.String), getPropertyValue(java.lang.String) error at line: 8
It works only for timestamp node.
any help please.
Thank you
It's because result.data is a list, so it returns a list (containing one item) for userid
You need to just get the first item from the list, so try:
testRunner.testCase.setPropertyValue("user_id", result.data.userid.head())

Resources