Append a value of a JSON inside another JSON in JMeter - json

By using the following script, I am able to generate the request payload for a request method.
import groovy.json.JsonSlurper
import groovy.json.JsonBuilder
def response = new groovy.json.JsonSlurper().parse(prev.getResponseData())
def builder = new JsonBuilder()
def finalRequest = [:];
def dicomTemp = builder.dicomTemplate
{
templateName "Default"
templateDesc "Default"
templateType "DEFAULT"
}
def dicomTags = builder.dicomTaS {
{
tagGroup "0002"
tagElement "0002"
tagName "Media Storage SOP Class UID"
updatedOn "2021-10-05T22:03:36.000+00:00"
labelValue 131074
mandatory "1"
}
{
tagGroup "0002"
tagElement "0010"
tagName "Transfer Syntax UID"
tagKeyword "TransferSyntaxUID"
createdOn "2021-06-02T20:40:59.000+00:00"
numericLabel "00020010"
labelValue 131088
mandatory "1"
}
}
finalRequest.put('studyDTO', true);
finalRequest.put('allSites', true);
finalRequest.put('allSubjects', true);
finalRequest.put('allStates', true);
finalRequest.put('allVisits', true);
finalRequest.put('modalities', response.modalities);
finalRequest.put('allModalities', true);
finalRequest.put('allExamDates', true);
finalRequest.put('allSeries', true);
finalRequest.put('transferType', "DICOM");
finalRequest.put('sftpLocations', response.sftpLocations)
finalRequest.put('dicomLocations', response.dicomLocations)
finalRequest.put('customFolder', null)
finalRequest.put('folderStructure', null)
finalRequest.put('customFile', null)
finalRequest.put('fileStructure', null)
finalRequest.put('includePS', null)
finalRequest.put('softEditOverride', true)
finalRequest.put('dicomTemplate', dicomTemp.dicomTemplate)
finalRequest.put('dicomTemplate.dicomTags', [dicomTags.dicomTaS])
vars.put('finalPayload',new groovy.json.JsonBuilder(finalRequest).toPrettyString());
But there are two corrections require here,
The dicomTags should be a key of dicomTemplate, but it is placed separately because of the declaration dicomTemplate.dicomTags. How to rectify this?
Can see the second value, want to include all the values
Like below

I think you need to change this:
def dicomTags = builder.dicomTaS {
{
tagGroup "0002"
tagElement "0002"
tagName "Media Storage SOP Class UID"
updatedOn "2021-10-05T22:03:36.000+00:00"
labelValue 131074
mandatory "1"
}
{
tagGroup "0002"
tagElement "0010"
tagName "Transfer Syntax UID"
tagKeyword "TransferSyntaxUID"
createdOn "2021-06-02T20:40:59.000+00:00"
numericLabel "00020010"
labelValue 131088
mandatory "1"
}
}
to this:
def dicomTags = builder {
dicomTaS(
[
{
tagGroup "0002"
tagElement "0002"
tagName "Media Storage SOP Class UID"
updatedOn "2021-10-05T22:03:36.000+00:00"
labelValue 131074
mandatory "1"
},
{
tagGroup "0002"
tagElement "0010"
tagName "Transfer Syntax UID"
tagKeyword "TransferSyntaxUID"
createdOn "2021-06-02T20:40:59.000+00:00"
numericLabel "00020010"
labelValue 131088
mandatory "1"
}
]
)
}
and this:
finalRequest.put('dicomTemplate', dicomTemp.dicomTemplate)
finalRequest.put('dicomTemplate.dicomTags', [dicomTags.dicomTaS])
to this:
dicomTemp.dicomTemplate.put('dicomTags', dicomTags['dicomTaS'])
finalRequest.put('dicomTemplate', dicomTemp.dicomTemplate)
also don't post code as screenshots and include everything we need to reproduce your issue (i.e. response object): How do I ask a good question?
More information:
Apache Groovy: Parsing and producing JSON
Apache Groovy: What Is Groovy Used For?

Related

Tornadofx REST client

I have followed an example shown here
link
And i got the hang of it, i managed to create my own "Employee" entity and i found some dummy api data online to play with.
like this Problem is, the tornadofx throws null pointer error, and i think its because the rest response sends something like this
{
"status": "success",
"data": [
{
"id": "1",
"employee_name": "Tiger Nixon",
"employee_salary": "320800",
"employee_age": "61",
"profile_image": ""
},
but when i use mocky and provide JUST the json part
[
{
"id": "1",
"employee_name": "Tiger Nixon",
"employee_salary": "320800",
"employee_age": "61",
"profile_image": ""
},...]
it all works fine.
I think those additional fields "status" and "success" in response confuse the rest client of tornadofx, and i cant manage to get it to work, is there anyway to tell client to ignore every other fields besides those of json data.
All links are functional, so you can try yourself.
full working example
package com.example.demo.view
import javafx.beans.property.SimpleIntegerProperty
import javafx.beans.property.SimpleStringProperty
import javafx.scene.layout.BorderPane
import tornadofx.*
import javax.json.JsonObject
class Employee (id:Int?=null , name: String? = null, age: Int?=null): JsonModel {
val idProperty = SimpleIntegerProperty(this, "id")
var id by idProperty
val ageProperty = SimpleIntegerProperty(this, "age")
var age by ageProperty
val employeeNameProperty = SimpleStringProperty(this, "name", name)
var name by employeeNameProperty
override fun updateModel(json: JsonObject) {
with(json) {
id = int("id")!!
age = int("employee_age")!!
name = string("employee_name")
}
}
override fun toJSON(json: JsonBuilder) {
with(json) {
add("id", id)
add("employee_name", name)
add("employee_age", age)
}
}
}
class PersonEditor : View("Person Editor") {
override val root = BorderPane()
val api : Rest by inject()
var persons = listOf(Employee(1,"John", 44), Employee(2,"Jay", 33)).observable()
val model = PersonModel(Employee())
init {
api.baseURI = "https://run.mocky.io/v3/"
val response = api.get("f17509ba-2d12-4c56-b441-69ab23302e43")
println(response.list())
println(response.list().toModel<Employee>()[0].name)
// print( p.get(1))
with(root) {
center {
tableview(response.list().toModel<Employee>()) {
column("Id", Employee::idProperty)
column("Name", Employee::employeeNameProperty)
column("Age", Employee::ageProperty)
// Update the person inside the view model on selection change
model.rebindOnChange(this) { selectedPerson ->
item = selectedPerson ?: Employee()
}
}
}
right {
form {
fieldset("Edit person") {
field("Id") {
textfield(model.id)
}
field("Name") {
textfield(model.name)
}
field("Age") {
textfield(model.age)
}
button("Save") {
enableWhen(model.dirty)
action {
save()
}
}
button("Reset").action {
model.rollback()
}
}
}
}
}
}
private fun save() {
// Flush changes from the text fields into the model
model.commit()
// The edited person is contained in the model
val person = model.item
// A real application would persist the person here
println("Saving ${person.employeeNameProperty} / ${person.ageProperty}")
}
}
class PersonModel(person: Employee) : ItemViewModel<Employee>(person) {
val id = bind(Employee::idProperty)
val name = bind(Employee::employeeNameProperty)
val age = bind(Employee::ageProperty)
}
if you replace base url and send request to http://dummy.restapiexample.com/api/v1/employees you will get an error that i am talking about
Your call to mocky returns a list, so .list() works fine. Your call to restapiexample, however, returns an object, not a list, so .list() won't do what you expect. You can probably use something like this, though I haven't tested it:
response.one().getJsonArray("data").toModel<Employee>()[0].name)
Further explanation:
If you're not familiar with the structure of JSON, check out the diagrams on the JSON homepage.
TornadoFX has two convenience functions for working with JSON returns: .list() and .one(). The .list() function will check if the result is a JsonArray. If so, it simply returns it. If it is instead a JsonObject, it wraps that object in a list and returns the new list.
In your case, since restapiexample is returning an object, the result of your call to .list() is a JsonArray with a single object. It looks something like this:
[
{
"status": "success",
"data": [...]
}
]
Obviously that single object cannot be converted to an Employee, so dereferencing anything off of it will result in a NullPointerException.
The .one() function on the other hand will check if the response is a JsonObject. If it is, it simply returns the object. If, however, the response is a JsonArray, it will take the first item from the array and return that item.

Parsing JSON using Groovy where array and multiple objects have no name to get list

new to groovy and coding in general. Trying to do the following:
(I have looked at many previous Q&As in stackoverflow but none of the solutions I found seem to work)
I have the following JSON from which I need to get a list/string of supplier names i.e. output should be something like : "supplier 1, supplier 2, supplier 3"
[
{
"id":217564,
"created-at":"2020-01-22T08:59:57+00:00",
"state":"submitted",
"supplier":
{
"name":"supplier 1"
}
},
{
"id":217565,
"created-at":"2020-01-22T09:00:00+00:00",
"state":"submitted",
"supplier":
{
"name":"supplier 2"
}
},
{
"id":217566,
"created-at":"2020-01-22T09:00:48+00:00",
"state":"submitted",
"supplier":
{
"name":"supplier 3"
}
}
]
I used the following groovy script to print out all the supplier names in a list:
import groovy.json.*;
#CustomScriptAction(
input = ['json_response'],
output = 'suppliers'
)
def CustomScriptAction14()
{
def object = new JsonSlurper().parseText(json_response.toString())
def suppliers = "No suppliers"
if(object != null && !object.isEmpty())
{
for(def i =0; i<object.size();i++)
{
suppliers = RString.of(object[i].'supplier'.name.toString());
}
}
return suppliers
}
I got the output: "supplier 3"
The issue is that this script is only giving me the last supplier in the loop instead of iterating through the entire loop and printing out all the suppliers. So I tried a different script:
import groovy.json.*;
#CustomScriptAction(
input = ['json_response'],
output = 'suppliers'
)
def CustomScriptAction14()
{
def object = new JsonSlurper().parseText(json_response)
def suppliers = object.findAll { it.value instanceof List }
.values()
.flatten()
.collect { [it.'supplier'.'name'] }
}
return suppliers
But with this I get a blank response.
What am I doing wrong?
Well this ended up working:
import groovy.json.*;
#CustomScriptAction(
input = ['json_response'],
output = 'suppliers'
)
def customScript()
{
def jsonSlurper = new JsonSlurper()
def object = jsonSlurper.parseText(json_response.toString())
suppliers = RString.of(object.'supplier'.'name'.toString())
}

NIFI:Json Content Parsing in FlowFile

I have text attribute in GenerateFlowfile processor like this:
[{
"status": {
"runStatus": "STOPPED"
},
"component": {
"state": "STOPPED",
"id": "ea5db028-015d-1000-5ad5-80fd006dda92"
},
"revision": {
"version": 46,
"clientId": "ef592126-015d-1000-bf4f-93c7cf7eedc0"
}
} ]
and related groovy script in my ExecuteScript processor :
import org.apache.commons.io.IOUtils
import java.nio.charset.*
def flowFile = session.get();
if (flowFile == null) {
return;
}
def slurper = new groovy.json.JsonSlurper()
def attrs = [:] as Map<String,String>
session.read(flowFile,
{ inputStream ->
def text = IOUtils.toString(inputStream, StandardCharsets.UTF_8)
text=flowFile.getAttribute('text')
def obj = slurper.parseText(text)
obj.each {k,v ->
attrs[k] = v.toString()
}
} as InputStreamCallback)
flowFile = session.putAllAttributes(flowFile, attrs)
session.transfer(flowFile, REL_SUCCESS)
but my processor still shows me exception like this, what should i change?
the problem that the root element of your json is an array
and you try to iterate it like map .each{k,v-> ... }
probably you want to take the first map to iterate it like in code below
def obj=[ [a:1] ]
//this line will throw exception:
//obj.each{k,v-> println "$k->$v" }
//but this one not
obj[0].each{k,v-> println "$k->$v" }
fyi: there is a EvaluateJsonPath processor that could extract attributes from json flowfile content and put result into attribute

UWP - From Json string to Structure (Classes)

I receive a JSon string from WS. It's so long that I can't use Json2charp to parse it and receive the structurated class.
I want to parse the string with a command. How is it possible?
I don't know the classes so I can't use a command like:
Dim result = JsonConvert.DeserializeObject(Of MyClass.RootObject)(String_From_File)
Is it possible from the string to obtain the class without using json2charp site ?
For example, in vs.net if on the variable 'string_from_file' I choose 'Json Visualizer' and see all classes and data in correct mode.
How can I obtain the same in my code ?
I have installed Newtonsoft.json
If you cannot use the json to class mappers like NewtonSoft.Json. You can use the Windows.Data.Json api. It let you parse and extract the data you want from your JSON string.
JsonValue jsonValue = JsonValue.Parse("{\"Width\": 800, \"Height\": 600, \"Title\": \"View from 15th Floor\", \"IDs\": [116, 943, 234, 38793]}");
double width = jsonValue.GetObject().GetNamedNumber("Width");
double height = jsonValue.GetObject().GetNamedNumber("Height");
string title = jsonValue.GetObject().GetNamedString("Title");
JsonArray ids = jsonValue.GetObject().GetNamedArray("IDs");
You can find a sample in the Windows Universal Sample GitHub.
A complex object parsing is shown here. I've extracted the most relevant parts here. The JSON string is provided to the User constructor which is extracting what it needs and then delegating the parsing to the nested School constructor.
{
"id": "1146217767",
"phone": null,
"name": "Satya Nadella",
"education": [
{
"school": {
"id": "204165836287254",
"name": "Contoso High School"
},
"type": "High School"
},
{
"school": {
"id": "116138758396662",
"name": "Contoso University"
},
"type": "College"
}
],
"timezone": -8,
"verified": true
}
This JSON fragment is parsed with this code:
public User(string jsonString) : this()
{
JsonObject jsonObject = JsonObject.Parse(jsonString);
Id = jsonObject.GetNamedString(idKey, "");
IJsonValue phoneJsonValue = jsonObject.GetNamedValue(phoneKey);
if (phoneJsonValue.ValueType == JsonValueType.Null)
{
Phone = null;
}
else
{
Phone = phoneJsonValue.GetString();
}
Name = jsonObject.GetNamedString(nameKey, "");
Timezone = jsonObject.GetNamedNumber(timezoneKey, 0);
Verified = jsonObject.GetNamedBoolean(verifiedKey, false);
foreach (IJsonValue jsonValue in jsonObject.GetNamedArray(educationKey, new JsonArray()))
{
if (jsonValue.ValueType == JsonValueType.Object)
{
Education.Add(new School(jsonValue.GetObject()));
}
}
}
public School(JsonObject jsonObject)
{
JsonObject schoolObject = jsonObject.GetNamedObject(schoolKey, null);
if (schoolObject != null)
{
Id = schoolObject.GetNamedString(idKey, "");
Name = schoolObject.GetNamedString(nameKey, "");
}
Type = jsonObject.GetNamedString(typeKey);
}
If you cannot use the automatic mapping from NewtonSoft.Json, you have no other way than doing it yourself.
Is not so simple.
The Json i received is very complicated and have many class
So i can't use
double width = jsonValue.GetObject().GetNamedNumber("Width");
Inside class i have more ...

Exclude null values using JSONBuilder in Groovy

Is it possible to create JSON values in Groovy using the default JsonBuilder library to exclude all the null values of an object? Such as what Jackson does in Java by annotating classes to exclude null values.
An example would be:
{
"userId": "25",
"givenName": "John",
"familyName": null,
"created": 1360080426303
}
Which should be printed as:
{
"userId": "25",
"givenName": "John",
"created": 1360080426303
}
Not sure if it's OK for you as my method works on a Map with List properties:
def map = [a:"a",b:"b",c:null,d:["a1","b1","c1",null,[d1:"d1",d2:null]]]
def denull(obj) {
if(obj instanceof Map) {
obj.collectEntries {k, v ->
if(v) [(k): denull(v)] else [:]
}
} else if(obj instanceof List) {
obj.collect { denull(it) }.findAll { it != null }
} else {
obj
}
}
println map
println denull(map)
yields:
[a:a, b:b, c:null, d:[a1, b1, c1, null, [d1:d1, d2:null]]]
[a:a, b:b, d:[a1, b1, c1, [d1:d1]]]
After filter null values out, you then can render the Map as JSON.
I used the Groovy metaClass to workaround this issue, but am not sure it would work in all cases.
I created a Class to hold the required elements, but left out the optional elements that could possibly have a null (or empty) value.
private class User {
def id
def username
}
Then, I added the data to this class. My use case was fairly complex so this is a simplified version just to show an example of what I did:
User a = new User(id: 1, username: 'john')
User b = new User(id: 2, username: 'bob')
def usersList = [a,b]
usersList.each { u ->
if (u.id == 1)
u.metaClass.hobbies = ['fishing','skating']
}
def jsonBuilder = new JsonBuilder([users: usersList])
println jsonBuilder.toPrettyString()
Results:
{
"users": [
{
"id": 1,
"username": "john",
"hobbies": [
"fishing",
"skating"
]
},
{
"id": 2,
"username": "bob"
}
]
}
If you do not need use JSONBuilder you can use com.fasterxml.jackson:
Make object:
private static final ObjectMapper JSON_MAPPER = new ObjectMapper().with {
setSerializationInclusion(JsonInclude.Include.NON_NULL)
setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE)
setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE)
}
and display your list of maps like that (maps can have any Object inside):
println(JSON_MAPPER.writeValueAsString(listOfMaps))
If you are using Groovy >2.5.0, you can use JsonGenerator. The example below is taken from Groovy's Documentation as of July 2018.
class Person {
String name
String title
int age
String password
Date dob
URL favoriteUrl
}
Person person = new Person(name: 'John', title: null, age: 21, password: 'secret',
dob: Date.parse('yyyy-MM-dd', '1984-12-15'),
favoriteUrl: new URL('http://groovy-lang.org/'))
def generator = new JsonGenerator.Options()
.excludeNulls()
.dateFormat('yyyy#MM')
.excludeFieldsByName('age', 'password')
.excludeFieldsByType(URL)
.build()
assert generator.toJson(person) == '{"dob":"1984#12","name":"John"}'