Like expression in JSON Path - json

I have a JOSN some thing like this
{
"Room" :{
"Book" :
{
"name" : "abc"
},
"Book1":
{
"name" : "xyz"
},
"Book3":
{
"name" : "abc123"
},
"Tv" :
{
"name" : "zyc"
},
"audio":
{
"name" :"sound ++"
}
}
}
From this JSON I want to filter out all book elements("book","book1","book2") using JSONPATH
As I got to know in in JSONPATH we do not have any "Like" type syntax , but we can do that by using regex.
I tried with this
$.Room[?(/^.*book.*$/i.test(#.Room))]
But this expression return nothing from the JSON.
Can any one help me out in this...

Maybe this link will be helpful for you . Check the table
$..book[?(#.author =~ /.*Tolkien/i)]. This expression brings All books whose author name ends with Tolkien (case-insensitive) --> Modify it for yours

Related

How to retrieve all key-value pairs avoiding key duplication from JSON in Groovy script

I am totally new to groovy script and would like some help to solve this out. I have a JSON response I want to manipulate and get desired parameters back by avoiding duplication. The Json response does not have indexes like 0,1,2.. that I can iterate through.
Here is the response that I want to work with:
{
"AuthenticateV2" : {
"displayName" : "Verification of authentication",
"description" : "notification ",
"smsTemplate" : "authentication.v2.0_sms",
"emailHeaderTemplate" : "v2.0_header",
"emailBodyTemplate" : "html",
"parameters" : {
"displayName" : "USER_DISPLAY_NAME",
"actionTokenURL" : "VERIFICATION_LINK",
"customToken" : "VERIFICATION_CODE"
},
"supportedPlans" : [
"connectGo"
]
},
"PasswordRecovery" : {
"displayName" : "Verification of password recovery",
"description" : "notification",
"smsTemplate" : "recovery.v1.0_sms",
"emailHeaderTemplate" : "recovery.v1.0_header",
"emailBodyTemplate" : "recovery.v1.0_body_html",
"parameters" : {
"displayName" : "USER_DISPLAY_NAME",
"actionTokenURL" : "VERIFICATION_LINK",
"customToken" : "VERIFICATION_CODE",
"adminInitiated" : false,
"authnId" : "AUTHENTICATION_IDENTIFIER",
"authnType" : "EMAIL",
"user" : {
"displayName" : "USER_DISPLAY_NAME"
}
},
"supportedPlans" : [
"connectGo"
]
},
"PasswordReset" : {
"displayName" : "password reset",
"description" : "notification",
"smsTemplate" : "recovery.v1.0_sms",
"emailHeaderTemplate" : "recovery.v1.0_header",
"emailBodyTemplate" : "html",
"parameters" : {
"displayName" : "USER_DISPLAY_NAME",
"user" : {
"displayName" : "USER_DISPLAY_NAME"
}
}
The expected output that I want to have:
{
"displayName" : "USER_DISPLAY_NAME",
"actionTokenURL" : "VERIFICATION_LINK",
"customToken" : "VERIFICATION_CODE",
"customToken" : "VERIFICATION_CODE",
"adminInitiated" : false,
"authnId" : "AUTHENTICATION_IDENTIFIER",
"authnType" : "EMAIL"
}
I need to retrieve all fields under parameters tag and also want to avoid duplication
You should first get familiar with parsing and producing JSON in Groovy.
Then, assuming the provided response is a valid JSON (it's not - there are 2 closing curlies (}) missing at the end) to get all the parameters keys merged into one JSON we have to convert the JSON string into a Map object first using JsonSlurper:
def validJsonResponse = '<your valid JSON string>'
Map parsedResponse = new JsonSlurper().parseText(validJsonResponse) as Map
Now, when we have a parsedResponse map we can iterate over all the root items in the response and transform them into the desired form (which is all the unique parameters keys) using Map::collectEntries method:
Map uniqueParameters = parsedResponse.collectEntries { it.value['parameters'] }
Finally, we can convert the uniqueParameters result back into a pretty printed JSON string using JsonOuput:
println JsonOutput.prettyPrint(JsonOutput.toJson(uniqueParameters))
After applying all the above we'll get the output
{
"displayName": "USER_DISPLAY_NAME",
"actionTokenURL": "VERIFICATION_LINK",
"customToken": "VERIFICATION_CODE",
"adminInitiated": false,
"authnId": "AUTHENTICATION_IDENTIFIER",
"authnType": "EMAIL",
"user": {
"displayName": "USER_DISPLAY_NAME"
}
}
If you want to get rid of user entry from the final output just remove it from the resulting uniqueParameters map (uniqueParameters.remove('user')) before converting it back to JSON string.

NiFi: Extract Content of FlowFile and Add that Content to the Attributes

I am generating random data from the following JSON/AVRO schema:
{
"type" : "record",
"namespace" : "test",
"name" : "metro_data",
"fields": [
{
"name" : "PersonID",
"type" : "int"
},
{
"name" : "TripStartStation",
"type" : {
"type" : "enum",
"name" : "StartStation",
"symbols" : ["WIEHLE_RESTON_EAST", "SPRING_HILL", "GREENSBORO"]
}
},
{
"name" : "TripEndStation",
"type" : {
"type" : "enum",
"name" : "EndStation",
"symbols" : ["WIEHLE_RESTON_EAST", "SPRING_HILL", "GREENSBORO""]
}
}
]
}
The above schema generates this, for example:
[ {
"PersonID" : -1089196095,
"TripStartStation" : "WIEHLE_RESTON_EAST",
"TripEndStation" : "SPRING_HILL"
}
I want to take the PersonID number of the schema, and add it to the Attributes. Eg, the blank in this photo needs to pull the actual PersonID number generated from the flow:
I have tried to use EvaluateJSONPath with the following configuration, and that's how I end up with the empty string set under PersonalID:
Is my next processor UpdateAttribute? Not sure how to pull that content. Thanks!
You are having array of json message(s)(ex: [...]) and You need to split the array of json into individual flowfiles using SplitJson processor with split expression as $.*
Then use EvaluateJsonProcessor to extract PersonID value as a attribute.
Flow:
--> SplitJson --> EvaluateJsonPath--> other processors
For more details refer to this link regards to the same issue.

Need help in generating REGEX for multi line JSON format

From the below JSON data, I want to cut out the attributes object and keep only Name of the Account. Sample JSON
{
"Accounts":[
{
"attributes":{
"type":"Account",
"url":"/services/data/v41.0/sobjects/Account/001S0000008mgjpIAA"
},
"Name":"Name+Test#Reseller"
},
{
"attributes":{
"type":"Account",
"url":"/services/data/v41.0/sobjects/Account/001S000000m5gyuIAA"
},
"Name":"Test Reseller Myself"
}
]
}
After matching with REGEX and replacing with "". The JSON should look like,
{
"Accounts" : [{
"Name" : "Name+Test#Reseller"
}, {
"Name" : "Test Reseller Myself"
}]
}
Use map and return only name property value
obj.accounts = obj.accounts.map( s => {Name: s.Name } );
I found myself an answer. I constructed a two regex
1. "attributes" : {\w*\W*\d*\D*\d*.\d*\D*\w*"\w*
2. {.\s*\S*

Search inside JSON with Elastic

I have an index/type in ES which has the following type of records:
body "{\"Status\":\"0\",\"Time\":\"2017-10-3 16:39:58.591\"}"
type "xxxx"
source "11.2.21.0"
The body field is a JSON.So I want to search for example the records that have in their JSON body Status:0.
Query should look something like this(it doesn't work):
GET <host>:<port>/index/type/_search
{
"query": {
"match" : {
"body" : "Status:0"
}
}
}
Any ideas?
You have to change the analyser settings of your index.
For the JSON pattern you presented you will need to have a char_filter and a tokenizer which remove the JSON elements and then tokenize according to your needs.
Your analyser should contain a tokenizer and a char_filter like these ones here:
{
"tokenizer" : {
"type": "pattern",
"pattern": ","
},
"char_filter" : [ {
"type" : "mapping",
"mappings" : [ "{ => ", "} => ", "\" => " ]
} ],
"text" : [ "{\"Status\":\"0\",\"Time\":\"2017-10-3 16:39:58.591\"}" ]
}
Explanation: the char_filter will remove the characters: { } ". The tokenizer will tokenize by the comma.
These can be tested using the Analyze API. If you execute the above JSON against this API you will get these tokens:
{
"tokens" : [ {
"token" : "Status:0",
"start_offset" : 2,
"end_offset" : 13,
"type" : "word",
"position" : 0
}, {
"token" : "Time:2017-10-3 16:39:58.591",
"start_offset" : 15,
"end_offset" : 46,
"type" : "word",
"position" : 1
} ]
}
The first token ("Status:0") which is retrieved by the Analyze API is the one you were using in your search.

Search within array object

I have a the following json object --
{
"Title": "Terminator,
"Purchases": [
{"Country": "US", "Site": "iTunes"},
{"Country": "FR", "Site": "Google"}
]
}
Given the above object, here is how the search results show yield:
"Titles on iTunes in US" ==> YES, show "Terminator"
"Titles on Google in FR" ==> YES, show "Terminator"
"Titles on iTunes in FR" ==> NO
However, if I just AND the query, to get Titles with Purchase.Country="FR" and Titles with Purchase.Site="iTunes", it would erroneously show the above result, since both conditions are met. However, I want to restrict that facet to within the purchase item. The equivalent in python code would be:
for purchase in item['Purchases']:
if purchase['Country'] == "FR" and purchase['Site'] == "iTunes":
return True
Currently it works like this:
for purchase in item['Purchases']:
if purchase['Country'] == "FR":
has_fr = True
if purchase['Site'] == "iTunes":
has_itunes = True
if has_itunes and has_fr: return True
How would this be done in ElasticSearch?
First, you need to index the "Purchases" field as a nested field, by defining the mapping of your object type like this:
{
"properties" : {
"Purchases" : {
"type" : "nested",
"properties": {
"Country" : {"type": "string" },
"Site" : {"type": "string" }
}
}
}
}
Only then will ElasticSearch keep the association between the individual countries and the individual sites, as described here.
Next, you should use a nested query, such as this one:
{ "query":
{ "nested" : {
"path" : "Purchases",
"score_mode" : "avg",
"query" : {
"bool" : {
"must" : [
{
"match" : {"Purchases.Country" : "US"}
},
{
"match" : {"Purchases.Site" : "iTunes"}
}
]
}
}
}
}
}
This will return your object if the query combines "US" and "iTunes", but not if it combines "US" and "Google". The details are described here.