Obtaining the child values randomly in JSON - json

I have a JSON like below: I need to extract the Options -> Child as a Random and also Values within the options as randomly. How can we achieve in jmeter ?
{
"id":37,
"merchant_id":"39",
"title":"Parker Pens",
"subtitle":null,
"price":1000,
"description":null,
"images":[ ],
"image_thumbs":[ ],
"options":[
{
"code":"color",
"label":"Color",
"extra_info":"",
"values":[
{ },
{ },
{ }
]
},
{
"code":"size",
"label":"Size",
"extra_info":"",
"values":[
{ },
{ },
{ }
]
}
],"options_available":[
{ },
{ },
{ },
{ },
{ },
{ },
{ },
{ },
{ }
], "custom_options":[
]
}
I have to fetch the child of options randomly . In that i have to fetch the value of "Code" and its associated value within the "Value" .
Help is appreciated and useful

Your requirements are a little bit vague as you haven't indicated what is the desired output format. One of the solutions would be using JSR223 PostProcessor in order to obtain the random value from random options array like:
import com.jayway.jsonpath.JsonPath
import org.apache.commons.lang3.RandomUtils
import org.apache.jmeter.samplers.SampleResult
def options = JsonPath.read(prev.getResponseDataAsString(), '$.options')
def randomOption = options.get(RandomUtils.nextInt(0, options.size()))
def values = randomOption.get('values')
def randomValue = values.get(RandomUtils.nextInt(0, values.size())) as String
vars.put('randomValue', randomValue)
References:
Jayway JsonPath - A Java DSL for reading JSON documents
Apache Groovy - Why and How You Should Use It
Apache Groovy - Parsing and Producing JSON

Related

How to select JSON array (JSON substring) in JasperReport with JSONQL?

I want to create a report using Jaspersoft Studio with a json file as datasource. I want to select some fields from this json and also a substring of the original json. This should be done by jsonql.
First, an example with the "JSON language" in JasperSoftStudio:
gives the following result:
This is exactly what I want to have, the delivery note number as a field, and the barcodes as an array of objects / json substring.
What I am not able to do is, to achieve this with jsonql. The following query
gives the result
The following json was used for this example
{
"tour": {
"shipments": [
{
"containers": [
{
"boxes": [
{
"customerModule": "DEFG",
"deliveryDateTime": "2022-04-25 11:49:24.834000",
"boxNumber": 2
},
{
"customerModule": "ABCD",
"deliveryDateTime": "2022-04-25 11:50:24.810000",
"boxNumber": 1
}
],
"licensePlate": "123"
}
],
"deliveryNoteNumber": "6785000",
"barcodes": [
{
"content": "barcode_01_04"
},
{
"content": "barcode_03_04"
},
{
"content": "barcode_04_04"
}
]
},
{
"containers": [
{
"boxes": [
{
"customerModule": "ZXYV",
"deliveryDateTime": "2022-04-25 11:51:24.834000",
"boxNumber": 1
},
{
"customerModule": "UHGI",
"deliveryDateTime": "2022-04-25 11:52:24.834000",
"boxNumber": 2
}
],
"licensePlate": "987"
}
],
"deliveryNoteNumber": "6785001",
"barcodes": [
{
"content": "Barcode_01_04"
},
{
"content": "Barcode_02_04"
},
{
"content": "Barcode_04_04"
}
]
}
],
"handlingDateTime": "2022-04-25 11:50:24.883000"
}
I tried to use this documentation, but I could not get it working.
The JSONQL data source doesn't properly convert arrays to Strings for some reason.
What you can do is change the barcodes field from java.lang.String to java.lang.Object. You can do that by clicking Edit in the Fields tab and changing the Class Type for the field.
With java.lang.Object as field type, the field value will be the underlying JSON (Jackson) model array object. You can do $F{barcodes}.toString() if you need to explicitly convert it to a String in an expression.

Reformat JSON with Groovy. Remove child node whilst keeping the contents

I am trying to reformat JSON to remove child nodes from some JSON objects whilst keeping whats inside the child node. (unsure how to explain, like removing the title node). In this example i am trying to have a JSONarray of groups without the UserGroup child node (whilst keeping each UserGroups content intact). Example JSON
{
"groups":[
{
"UserGroup":{
"integrationKey":"0000073807",
"uid":"0000073807"
},
"UserGroup":{
"integrationKey":"0000073810",
"uid":"0000073810"
}
}
]
}
What I'd like after processing
{
"groups":[
{
"integrationKey":"0000073807",
"uid":"0000073807"
},
{
"integrationKey":"0000073810",
"uid":"0000073810"
}
]
}
For the JSON with no duplicated keys, which formats the data, removing child keys may look like
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
def inputJson = '''
{
"groups": [{
"UserGroup1": {
"integrationKey": "0000073807",
"uid": "0000073807"
},
"UserGroup2": {
"integrationKey": "0000073810",
"uid": "0000073810"
}
}
]
}
'''
Map parsed = new JsonSlurper().parseText(inputJson) as Map
parsed.each {
parsed[it.key] = it.value*.values().flatten()
}
println JsonOutput.toJson(parsed)
This code will print
{"groups":[{"integrationKey":"0000073807","uid":"0000073807"},{"integrationKey":"0000073810","uid":"0000073810"}]}
Handle duplicated key
But your provided input example contains 2 items with UserGroup name. It's not common for JSON and most parsers just take the last mentioned value for the key. To handle this you can use below dependency
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
And modify the above script to
import net.sf.json.JSONObject
// ...
ipuptJson = JSONObject.fromObject(inputJson).toString()
Map parsed = new JsonSlurper().parseText(inputJson) as Map
parsed.each {
parsed[it.key] = it.value*.values().flatten()
}
println JsonOutput.toJson(parsed)
Starting from terminology, you are not really modifiyng the json itself. In fact you can modify the in-memory representation of it exposed as a mixture of Lists, Maps and primitive object types.
The simplest way to do what you want would be:
import groovy.json.*
def json = new JsonSlurper().parseText '''
{
"groups": [{
"UserGroup1": {
"integrationKey": "0000073807",
"uid": "0000073807"
},
"UserGroup2": {
"integrationKey": "0000073810",
"uid": "0000073810"
}
}
]
}
'''
def modified = [ groups:json.groups*.values().flatten() ]
println JsonOutput.prettyPrint( JsonOutput.toJson( modified ) )
prints:
{
"groups": [
{
"integrationKey": "0000073807",
"uid": "0000073807"
},
{
"integrationKey": "0000073810",
"uid": "0000073810"
}
]
}

convert a JSON to another w/ circe

I would like to convert this JSON
{
"l1k1": {
"l2k1": "l2v1",
"l2k2": 1
},
"l1k2": [
{
"e1l1": "e1v1",
"e1l2": "e1v2"
},
{
"e2l1": "e2v1",
"e2l2": "e2v2"
}
]
}
to this one
{
"papa": {
"l1k1c": {
"l2k1c": {
"string": "l2v1"
},
"l2k2c": {
"int": 1
}
},
"l1k2c": {
"array": [
{
"e1l1": "e1v1",
"e1l2": "e1v2"
},
{
"e2l1": "e2v1",
"e2l2": "e2v2"
}
]
}
}
}
where:
"l" stands for level
"k" for key, "v" for value
"e" for element
"c" for copy (where "*" maps to "*c")
I'm using circe's Json but having a hard time renaming the keys or creating parents or children with it. As I'm writing this, I'm thinking I may need to use its ACursor instead. As you may have guessed, I'm trying to generate an AVRO doc from an input JSON. I'm open to help w/ my approach or any suggestions about how to go about it in a cleaner way.

How to update a key value in JSON dynamically?

I have a JSON like below
{
"context":{
"parameters":[
{
"name":"stub",``
"value": {"item value":"abcdefg"}
},
{
"name":"category",
"value":{"item value":"cars"}
},
{
"name":"year",
"value":{"item value":"2012"}
},
{
"name":"make",
"value":{"item value":"toyota"}
},
{
"name":"cars",
"value":{"item value":"corolla"}
}
]
}
I am supplied with a two strings dynamically like "cars" and "accord". I need to search for "cars" and then replace the "item value" under it to "accord". I have tried to convert it to map but have no success.
Any suggestions about how I can achieve this?
Here's one way to do it in Groovy.
Assuming that the JSON is like so (I have corrected it; there are illegal chars in the original question):
def s = '''
{
"context":{
"parameters":[
{
"name":"stub",
"value": {"item value":"abcdefg"}
},
{
"name":"category",
"value":{"item value":"cars"}
},
{
"name":"year",
"value":{"item value":"2012"}
},
{
"name":"make",
"value":{"item value":"toyota"}
},
{
"name":"cars",
"value":{"item value":"corolla"}
}
]
}
}
'''
then consider:
import groovy.json.*
def jsonSlurper = new JsonSlurper().parseText(s)
def category = jsonSlurper.context.parameters.find { it.name == "cars" }
category.value."item value" = "accord"
println new JsonBuilder(jsonSlurper).toPrettyString()
you can do that with javascript. If you are working with JSON format you can parse that data to an object.
const data = JSON.parse("your json data")
data.context.parameters.map(param => {
if ( param.name !== "cars") {
return param
}
return {
"name": "cars",
value: {"accord": "corolla"}
}
})

How to get array number with groovy script in SoapUI?

I want to assert the value of a property in Json response with the use of Groovy script in SoapUI. I know a value for name but I need to know on which position the id is.
json response example:
{
"names":[
{
"id":1,
"name":"Ted"
},
{
"id":2,
"name":"Ray"
},
{
"id":3,
"name":"Kev"
}
]
}
Let's say I know that there is a name Ray, I want the position and the id (names[1].id)
Here is the script to find the same:
import groovy.json.*
//Using the fixed json to explain how you can retrive the data
//Of couse, you can also use dynamic value that you get
def response = '''{"names": [ { "id": 1, "name": "Ted", }, { "id": 2, "name": "Ray", }, { "id": 3, "name": "Kev", } ]}'''
//Parse the json string and get the names
def names = new JsonSlurper().parseText(response).names
//retrive the id value when name is Ray
def rayId = names.find{it.name == 'Ray'}.id
log.info "Id of Ray is : ${rayId}"
//Another way to get both position and id
names.eachWithIndex { element, index ->
if (element.name == 'Ray') {
log.info "Position : $index, And Id is : ${element.id}"
}
}
You can see here the output