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"
}
]
}
Related
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
I am trying to get data from DynamoDB using GetDynamoDB processor in nifi, I have provided all the mandatory fields except Json Document attribute, I don't know what to set in that field.
Input Data :
{
"ProductCatalog": [
{
"PutRequest": {
"Item": {
"Id": {
"N": "101"
},
"Title": {
"S": "Book 101 Title"
},
"ISBN": {
"S": "111-1111111111"
},
"Authors": {
"L": [
{
"S": "Author1"
}
]
},
"Price": {
"N": "2"
},
"Dimensions": {
"S": "8.5 x 11.0 x 0.5"
},
"PageCount": {
"N": "500"
},
"InPublication": {
"BOOL": true
},
"ProductCategory": {
"S": "Book"
}
}
}
}]
}
Any one can be appreciated.
When you store a JSON document in DynamoDB, the JSON document you store is placed as a nested object inside a wrapper object known as a DynamoDB Item, which stores metadata about the document. The Json Document attribute lets you specify the key in the DynamoDB Item for the nested JSON document so that it can be extracted from the top-level DynamoDB Item.
Looking at the source code for the GetDynamoDB NiFi processor shows how the value (jsonDocument) is used to call the AWS DynamoDB SDK, extract the JSON for the specified DynamoDB Item attribute, and create a NiFi FlowFile for the contents:
BatchGetItemOutcome result = dynamoDB.batchGetItem(tableKeysAndAttributes);
// Handle processed items and get the json document
List<Item> items = result.getTableItems().get(table);
for (Item item : items) {
ItemKeys itemKeys = new ItemKeys(item.get(hashKeyName), item.get(rangeKeyName));
FlowFile flowFile = keysToFlowFileMap.get(itemKeys);
if ( item.get(jsonDocument) != null ) {
ByteArrayInputStream bais = new ByteArrayInputStream(item.getJSON(jsonDocument).getBytes());
flowFile = session.importFrom(bais, flowFile);
}
session.transfer(flowFile,REL_SUCCESS);
keysToFlowFileMap.remove(itemKeys);
}
Hope this helps!
Json Document attribute is which key inside your DynamodDB item do you want to become the content for the downstream flowfile.
Current, there is no way to only return the entire 'root' DynamoDB item, only inside attributes.
Below an example flow:
DynamoDB Table:
GetDynamoDB:
Inside the GenerateFlowFile I'm creating a FlowFile with the attributes hash_key and range_key.
If I configure the Json Document attribute as json the output FlowFile content would be {"key1":"name","key2":2}.
If I configure as attribute the output would be "attribute".
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
Hi i have a json like this called body:
{
data: {
id:1,
name:hallo
},
paging: {
cursors: {
next: "abc"
}
}
}
so I have to save it into a map and then I'll need to print or to modify it.
If I save it with this code
var Map = require("collections/map");
var new_body = JSON.parse(body)
var map = new Map(new_body);
I have some difficulties to print for example map.paging.cursor.next, how can I do it? maybe I had to define a structure of that map before inserting the json inside it, I don't know...
Your json have errors. Correct them like this.
{
"data": {
"id": 1,
"name": "hallo"
},
"paging": {
"cursors": {
"next": "abc"
}
}
}
Then you can parse the json like this and get the paging.cursors.next value.
var map = JSON.parse(body);//This will parse the json string
Now map.paging.cursors.next will have the value "abc"
For the following domain model:
class Route {
String name
static hasMany = [checkPoints:CheckPoint]
static belongsTo = [someBigObject:SomeBigObject]
static mapping = {
checkPoints lazy: false
}
}
I need to return a specific Route as a JSON from a web service. And I want this JSON to contain all the checkPoints but no other compositions (i.e.:someBigObject).
If I do
def route = Route.findById(id)
render route as JSON
all I got is the id's of the checkPoints, no other field is fetched:
{
"class": "com.example.Route",
"id": 1,
"checkPoints": [
{
"class": "CheckPoint",
"id": 1
},
{
"class": "CheckPoint",
"id": 2
},
{
"class": "CheckPoint",
"id": 4
},
{
"class": "CheckPoint",
"id": 3
}
],
"someBigObject": {
"class": "SomeBigObject",
"id": 2
}
}
but if I do
JSON.use('deep') {
render route as JSON
}
I get everything. I mean, almost all the database is getting fetched through various relationships.
Is there way to do this without creating the jsonMaps manually?
You can register your own JSON marshaller for chosen classes and return properties which you want to render. Map can be done automatically by iteration over class fields. Marshaller ca be registered for example in bootstrap or in domain class during creation.
JSON.registerObjectMarshaller(Route) {
return [name:it.name, checkPoints:it.checkPoints]
}
There is nice article about it under: http://manbuildswebsite.com/2010/02/15/rendering-json-in-grails-part-3-customise-your-json-with-object-marshallers/
Hope it helps