trying to create the below json structure with groovy jsonBuilder in jmeter using JSR223 sampler
{
"Catalogues":[
{
"Catalogue":{
"itemName":"XYZ",
"Level":"Class1",
"Color":"Orange",
"Id":"232f2d6820822840"
},
"sales":[
[
"7:19 PM 3-31-2022",
"gadfma53742w3585657er43"
],
[
"5:02 PM 3-30-2022",
"iytyvh53742w3585657er41"
]
]
}
]
}
I have tried the below groovy script
def json = new groovy.json.JsonBuilder()
json {
Catalogues(
[{
Catalogue {
itemName('XYZ')
Level('Class1')
Color('Orange')
Id('232f2d6820822840')
},
{
sales(
('7:19 PM 3-31-2022'), ('gadfma53742w3585657er43')
)
}
}]
)
}
log.info '\n\n\n' + json.toPrettyString() + '\n\n\n'
Output:
{
"Catalogues":[
{
"Catalogue":[
{
"itemName":"XYZ",
"Level":"Class1",
"Color":"Orange",
"Id":"232f2d6820822840"
},
{
"sales":[
"7:19 PM 3-31-2022",
"gadfma53742w3585657er43"
]
}
]
}
]
}
Problems:
If I remove the '{' before sales and after (at corresponding location), it adds sales values into catalogue
unable to include second set of sales values
I'm suggesting another way to use builder because it's easier to understand.
To declare array in groovy use [1, 2, 3]
To declare map [a:1, b:2, c:3]
So, if you replace in original json { to [ - you will get valid groovy object that corresponds to parsed json
def data = [
"Catalogues":[
[
"Catalogue":[
"itemName":"XYZ",
"Level":"Class1",
"Color":"Orange",
"Id":"232f2d6820822840"
},
"sales":[
[
"7:19 PM 3-31-2022",
"gadfma53742w3585657er43"
],
[
"5:02 PM 3-30-2022",
"iytyvh53742w3585657er41"
]
]
]
]
]
//then you could convert it to json:
def json = new groovy.json.JsonBuilder(data).toPrettyString()
log.info(json)
JsonBuilder translates Map to JSON Object and List to JSON Array
So I would recommend for better readability and clarity amending your code to look like:
def body = [:]
def Catalogues = []
def Catalogue = [:]
def entry = [:]
Catalogue.put('itemName', 'XYZ')
Catalogue.put('Level', 'Class1')
Catalogue.put('Color', 'Orange')
Catalogue.put('Id', '232f2d6820822840')
def sales = []
sales.add(['7:19 PM 3-31-2022', 'gadfma53742w3585657er43'])
sales.add(['5:02 PM 3-30-2022', 'iytyvh53742w3585657er41'])
entry.put('Catalogue', Catalogue)
entry.put('sales', sales)
Catalogues.add(entry)
body.put('Catalogues', Catalogues)
def json = new groovy.json.JsonBuilder(body)
More information:
JsonBuilder
Apache Groovy - Parsing and producing JSON
Apache Groovy - Why and How You Should Use It
Related
I would like to remove the array SEO from the json when the keys "Description" and "Title" in the has no value.
json:
[
{
"SEO": [
{
"Description": "",
"Title": ""
}
],
"accesoires": [
"1167296"
],
"shortCode": "S-576",
"spareParts": [
"800236"
]
}]
I tried the below code but i'm not able to remove the array.
def Message processData(Message message) {
def body = message.getBody(String);
def json = new JsonSlurper().parseText(body)
json.each{
it.SEO.each{
if(!(it.findResults{k, v -> v?.size() > 0 && v[0]?.length() > 0 ? v[0] : null })){
json.remove("SEO")
} } }
def out= JsonOutput.toJson(json)
message.setBody(out)
return message}
To remove the array "SEO" from the JSON when the keys "Description" and "Title" have no value, you can use the following Groovy code:
def jsonString = '[{"SEO": [{"Description": "", "Title": ""}], "accesoires": ["1167296"], "shortCode": "S-576", "spareParts": ["800236"]}]'
def json = new JsonSlurper().parseText(jsonString)
for (item in json) {
if (!item.SEO[0].Description && !item.SEO[0].Title) {
item.remove('SEO')
}
}
println(JsonOutput.toJson(json))
This will first parse the JSON string into a list of maps using JsonSlurper. Then it iterates through each map in the list and checks if the "Description" and "Title" keys in the "SEO" array are empty. If they are, it removes the "SEO" array from the map using the remove() method. Finally, it prints the modified JSON using the JsonOutput.toJson() method.
Environmant:
Micronaut: 3.7.3
Java: OpenJDK 11.0.16
Groovy: 3.0.13
My Controller is implemented with Groovy as below:
#Controller("/")
#Slf4j
class Controller1 {
#Get(uri="/test-localdatetime", produces = MediaType.APPLICATION_JSON)
HttpResponse<String> testLocalDateTime() {
LocalDateTime now = LocalDateTime.now()
def map = [
status: "SSUCCESS",
time: now
]
return HttpResponse.ok(map)
}
}
When I call it, it returns:
{"status":"SSUCCESS","time":[2022,11,2,8,24,13,948454300]}
If I want it to return a beautified JSON as below, I could add below code
String json = new JsonBuilder(map).toPrettyString()
return HttpResponse.ok(json)
And the response will become (still not what I want):
{
"status": "SSUCCESS",
"time": {
"month": "NOVEMBER",
"second": 29,
"hour": 8,
"nano": 944749300,
"year": 2022,
"dayOfMonth": 2,
"minute": 44,
"monthValue": 11,
"dayOfWeek": "WEDNESDAY",
"chronology": {
"calendarType": "iso8601",
"id": "ISO"
},
"dayOfYear": 306
}
}
But the idea response I want is below format:
{
"status":"SSUCCESS",
"time":"2022-11-02 08:24:13"
}
So, I wonder if there is an easy way to reach the above idea format by just adding some configurations or annotations without changing the intial code ?
you need to configure the jackson serialization yourself in the application.yml
jackson:
dateFormat: yyyyMMdd
timeZone: UTC
serialization:
writeDatesAsTimestamps: false
By the way, I strongly recommend to use a java.time.Instant over java.time.LocalDateTime.
Furthermore I would change the return type of your controller to return a Map instead of a String so the framework can care about serialising the Map, since you are returning a map and not a string.
#Controller("/")
#Slf4j
class Controller1 {
#Get(uri="/test-localdatetime", produces = MediaType.APPLICATION_JSON)
HttpResponse<Map> testLocalDateTime() {
def map = [
status: "SUCCESS",
time: Instant.now()
]
return HttpResponse.ok(map)
}
}
When you use date/time only on one place or you need to have different formats on different places then you can:
Return DTO where you can set format by annotation
Example DTO class
import com.fasterxml.jackson.annotation.JsonFormat
import java.time.LocalDateTime
class SomeResponse {
String status
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime time
}
Controller method:
#Get(uri="/test-localdatetime", produces = MediaType.APPLICATION_JSON)
SomeResponse testLocalDateTime() {
new SomeResponse(
status: "SSUCCESS",
time: LocalDateTime.now()
)
}
Continue using Map but convert the time value manually
Controller changes:
final static def formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
#Get(uri="/test-localdatetime", produces = MediaType.APPLICATION_JSON)
Map testLocalDateTime() {
def now = LocalDateTime.now()
[
status: "SSUCCESS",
time: formatter.format(now)
]
}
I have the following JSON object r2,
[
{
"reserva_id":"200",
"estancias":[
{
"reserva_estancia":"266",
"huespedes":[
{
"reserva_huesped":"272",
"reserva_estancia":"266",
"numero_huesped":"1",
"huesped":"123",
"huesped_nombre":"dos dos, dos",
"rfid":null
},
{
"reserva_huesped":"276",
"reserva_estancia":"266",
"numero_huesped":"2",
"huesped":"183",
"huesped_nombre":"MUESTRA MUESTRA, CARMEN",
"rfid":null
}
]
}
]
},
{
"reserva_id":"201",
"estancias":[
{
"huespedes":[
{
"reserva_huesped":"273",
"reserva_estancia":"267",
"numero_huesped":"1",
"huesped":"148",
"huesped_nombre":"MUESTRA MUESTRA, CARMEN",
"rfid":null
},
{
"reserva_huesped":"277",
"reserva_estancia":"267",
"numero_huesped":"2",
"huesped":"187",
"huesped_nombre":"TEST TEST, TESTCIVITFUN",
"rfid":null
}
]
}
]
}
]
I am trying to get the first huesped for each reservation, and for that I am using the following script, to create a list called profiles and store profileId's:
def profiles = jsonpath(r2,'$..[:].estancias[:].huespedes[0].huesped')
The output should be the following:
[
"123",
"148"
]
However, when I print profiles.text I get all the content of the estancias object, instead of just the huesped number.
When using Jayway's JSONPath like this I get the desired oputput:
$..[*].estancias[*].huespedes[0].huesped
You can try the path expression with your JSON here online.
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);
I want to get data from thisarray of json object :
[
{
"outgoing_relationships": "http://myserver:7474/db/data/node/4/relationships/out",
"data": {
"family": "3",
"batch": "/var/www/utils/batches/d32740d8-b4ad-49c7-8ec8-0d54fcb7d239.resync",
"name": "rahul",
"command": "add",
"type": "document"
},
"traverse": "http://myserver:7474/db/data/node/4/traverse/{returnType}",
"all_typed_relationships": "http://myserver:7474/db/data/node/4/relationships/all/{-list|&|types}",
"property": "http://myserver:7474/db/data/node/4/properties/{key}",
"self": "http://myserver:7474/db/data/node/4",
"properties": "http://myserver:7474/db/data/node/4/properties",
"outgoing_typed_relationships": "http://myserver:7474/db/data/node/4/relationships/out/{-list|&|types}",
"incoming_relationships": "http://myserver:7474/db/data/node/4/relationships/in",
"extensions": {},
"create_relationship": "http://myserver:7474/db/data/node/4/relationships",
"paged_traverse": "http://myserver:7474/db/data/node/4/paged/traverse/{returnType}{?pageSize,leaseTime}",
"all_relationships": "http://myserver:7474/db/data/node/4/relationships/all",
"incoming_typed_relationships": "http://myserver:7474/db/data/node/4/relationships/in/{-list|&|types}"
}
]
what i tried is :
def messages=[];
for ( i in families) {
messages?.add(i);
}
how i can get familes.data.name in message array .
Here is what i tried :
def messages=[];
for ( i in families) {
def map = new groovy.json.JsonSlurper().parseText(i);
def msg=map*.data.name;
messages?.add(i);
}
return messages;
and get this error :
javax.script.ScriptException: groovy.lang.MissingMethodException: No signature of method: groovy.json.JsonSlurper.parseText() is applicable for argument types: (com.tinkerpop.blueprints.pgm.impls.neo4j.Neo4jVertex) values: [v[4]]\nPossible solutions: parseText(java.lang.String), parse(java.io.Reader)
Or use Groovy's native JSON parsing:
def families = new groovy.json.JsonSlurper().parseText( jsonAsString )
def messages = families*.data.name
Since you edited the question to give us the information we needed, you can try:
def messages=[];
families.each { i ->
def map = new groovy.json.JsonSlurper().parseText( i.toString() )
messages.addAll( map*.data.name )
}
messages
Though it should be said that the toString() method in com.tinkerpop.blueprints.pgm.impls.neo4j.Neo4jVertex makes no guarantees to be valid JSON... You should probably be using the getProperty( name ) function of Neo4jVertex rather than relying on a side-effect of toString()
What are you doing to generate the first bit of text (which you state is JSON and make no mention of how it's created)
Use JSON-lib.
GJson.enhanceClasses()
def families = json_string as JSONArray
def messages = families.collect {it.data.name}
If you are using Groovy 1.8, you don't need JSON-lib anymore as a JsonSlurper is included in the GDK.
import groovy.json.JsonSlurper
def families = new JsonSlurper().parseText(json_string)
def messages = families.collect { it.data.name }