Getting a single value from a JSON object using JSONPath - json

I have the following JSON and I need to get the plain name value using JSONPath:
{
"single" : {
"id" : 1,
"name" : "Item name"
}
}
Expression that I used is $.single.name but I always get an array:
[ "Item name" ]
instead of a string value ("Item name").

but I always get an array:
That is meant to happen. As you can read in this documentation, under 'Result' (almost at the bottom):
Please note, that the return value of jsonPath is an array, which is
also a valid JSON structure. So you might want to apply jsonPath to
the resulting structure again or use one of your favorite array
methods as sort with it.
So basically it will always return an array. If you need the data as an other type, e.g. a String in this case, you will have to do the conversion yourself I'm afraid.

I was using the Java implementation of JSONPath and got to the very same issue. What worked for me was to add '[0]' to the json path string. So in your case:
$.single.name[0]

I think, it depends of language implementation.
For example in nodejs there is a npm module : https://www.npmjs.com/package/jsonpath
Which have a method called value, which does exactly what we need
jp.value(obj, pathExpression[, newValue])
Returns the value of the first element matching pathExpression. If newValue is provided, sets the value of the first matching element and returns the new value.
I tried it and worked!

In case you got this error
"Unable to get a scalar value for expression $.yourfield"
You have just to configure the EvaluateJsonPath processor by changing the return type property value to 'json' instead of 'auto-detect'

Related

Elasticsearch 8.0.0 mapper_parsing_exception of a string literal for field type "flattened"

I have a Problem to insert a document via Api to my ES 8.0.0.
In my IndexTemplate I defined a mapping of a property called [Data] of type "flattend".
For "normal" JSON-Objects it works fine. But when I try to insert a plain string literal (for example "test") or a number (for example 4) I get a "400 Bad Request". JSONLint says it's a valid JSON!!
{
....
"Data": "test",
....
}
Can i configure ES to accept such kind of JSON for type "flattened"??
As Elasticsearch document mentions:
The flattened type provides an alternative approach, where the entire
object is mapped as a single field. Given an object, the flattened
mapping will parse out its leaf values and index them into one field
as keywords.
So, the value provided for the "flattened" field type should be a JsonObject.
Hence, below works as where "full_name" is of type "flattened"
"full_name":{
"name":"nishikant"
}
But below does not
"full_name":"nishikant".
Same has been given in exception
"reason" : "Failed to parse object: expecting token of type [START_OBJECT] but found [VALUE_STRING]"

Selecting property from nested JSON array stored within Logic App variable

I am struggling to select a property from a JSON array that I've stored in a variable (as an array). I receive the following error:
The execution of template action 'Select' failed: The evaluation of 'query' action >'where' expression '{
"Response": "#variables('UserEvents').responseStatus.response",
"trest": ""
}' failed: 'The template language expression >'variables('UserEvents').responseStatus.response' cannot be evaluated because property >'responseStatus' cannot be selected. Array elements can only be selected using an > integer index. Please see https://aka.ms/logicexpressions for usage details.'.
The JSON is below:
[
{
"value": [
{
"responseStatus": {
"response": "notResponded",
"time": "0001-01-01T00:00:00Z"
}
}
]
}
]
I'm trying to select the 'response' property only by using the following expression:
#variables('UserEvents').responseStatus.response
I have tried adding [0] to various parts of the above expression but it doesn't seem to make any difference. I am sure it's pretty simple and I'm just getting the syntax wrong, but am completely stuck!
Any help appreciated - thanks.
Adrian
#{
variables('UserEvents') ? ['value'] ? [0] ? ['response']
}
Try that. The integer index mentioned in the error is the way around this. May need to play around with the structure to make it match your data but [0] will make it select the first object within your value array.
There are 2 ways to get the properties inside a nested JSON
WAY - 1 (Try to get properties using For-each loop)
For this we need to use 2 for-each loops to retrieve the property inside the nested JSON After Parsing the JSON. Below is the screenshot of my logic app for your reference.
WAY - 2 (Using Dynamic Expression)
Here is the Expression that worked for me.
body('Parse_JSON')?[0]?['value']?[0]?['responseStatus']?['response']
Since it is in Array of Array format we need to mention the index of the array. Below is the screenshot of my logic app for your reference :
output :

How the JSON value extract process in jmeter response data using regular expression extractor

{
"response":{
"statusCode":"00",
"status":"success",
"responseData":
[
{
"status":1,
"themeID":27,
"themeName":"ThemeName25",
"templateId":22
}
},
{
"status":1,
"themeID":28,
"themeName":"ThemeName28",
"templateId":28
}
}
]
}
Here need to extract the json values from first and second array But without the use of jmeter plugins like JSON PATH EXTRACTOR. Can anyone suggest the idea for this?
Regular Expression Extractor is usually much faster compared to other extractors like XPath, JSON etc - Check this site for the comparison.
Lets assume we are trying to get the value of all the theme ids from the JSON.
Add a Regular Expression Extractor and update the details as shown here.
You need a reference name to store the value found
The pattern to check
Template used to create a string from the matches found
-1 for all matches, 0 for random, 1 for first ..etc
<variable>_matchNr will give the total matches
theme.id_1 will return the first match which is 27
theme.id_2 will return the second match which is 28
More details and examples are here.

JSON decoding in PERL - Maintaining the original data type

I am writing a simple perl script to read JSON from a file and insert into MongoDB. But I am facing issues with json decoding.
All non-string values in my original json are getting converted to object type after decode_json.
Input JSON(only part of it since it's original is huge) -
{
"_id": 2006010100000801089,
"show_image" : false,
"event" : "publish",
"publish_date" :1136091600,
"data_version" : 1
}
JSON that gets inserted to MongoDB -
{
"_id": NumberLong("2006010100000801089"),
"show_image" : BinData(0,"MA=="),
"event" : "publish",
"publish_date" :NumberLong(1136091600),
"data_version" : NumberLong(1)
}
I am providing the custom _id for the documents, which I want to get converted to NumberLong type. That is working as expected as you can see from the JSON above. But notice how other non-string values for show_image, publish_date and data_version got converted to it's object representation.
Is there any way I can retain the original type for these values?
Perl code snipper that does the insert -
use MongoDB;
use MongoDB::OID;
use JSON;
use JSON::XS
while(my $record = <$source_file>) {
my $record_decoded = decode_json($record);
$db_collection->insert($record_decoded);
}
Perl version used v5.18.2.
I looked up JSON::XS docs but couldn't find a way to do this. Any help is appreciated. Thanks in advance!
I am very new to perl. Sorry if this is a trivial question.
I am providing the custom _id for the documents, which I want to get converted to NumberLong type. That is working as expected as you can see from the JSON above. But notice how other non-string values for show_image, publish_date and data_version got converted to it's object representation.
From your example all of the data types are actually matching aside from the boolean value for show_image which is currently being converted to binary data.
It is expected that numeric types are displayed as NumberLong or NumberInt when queried from the mongo shell. The mongo shell uses JavaScript, which only has a single numeric type of Number (64-bit floating point). Shell helpers like NumberLong() and NumberInt() are used to represent values in MongoDB's BSON data types that do not have a native JavaScript equivalent.
Referring to my sample JSON, I want value of show_image to be inserted as false instead of BinData(0,"MA==") and publish_date to be inserted as 1136091600 instead of NumberLong(1136091600)
While it's OK to insert publish_date as a Unixtime if that suits your use case, you may find it more useful to use MongoDB's Date type instead. There are convenience methods for querying dates including Date Aggregation Operators. FYI, date fields will be displayed in the mongo shell with an ISODate() wrapper.
The boolean value for show_image definitely needs an assist, though.
If you use Data::Dumper to inspect the result from decode_json(), you will see that the show_image field is a blessed object:
'show_image' => bless( do{\(my $o = 0)}, 'JSON::PP::Boolean' )
In order to get the expected boolean value in MongoDB, the recommended approach in the MongoDB module docs is to use the boolean module (see: MongoDB::DataTypes).
I couldn't find an obvious built-in option for JSON or JSON::XS to support serialising booleans to something other than the JSON emulated boolean class, but one solution would be to use the Data::Clean::Base module which is part of the Data::Clean::JSON distribution.
Sample snippet (excluding the MongoDB set up):
use Data::Clean::Base;
use boolean;
my $cleanser = Data::Clean::Base->new(
'JSON::XS::Boolean' => ['call_func', 'boolean::boolean'],
'JSON::PP::Boolean' => ['call_func', 'boolean::boolean']
);
while (my $record = <$source_file>) {
my $record_decoded = decode_json($record);
$cleanser->clean_in_place($record_decoded);
$db_collection->insert($record_decoded);
}
Sample record as saved in MongoDB 3.0.2:
{
"_id": NumberLong("2006010100000801089"),
"event": "publish",
"data_version": NumberLong("1"),
"show_image": false,
"publish_date": NumberLong("1136091600")
}
JSON data contains only (double-precision) numbers, strings, and the special values true, false, and null. They can be arranged in arrays or "objects" (hashes).
The MongoDB engine is converting these basic types into something more complex, but the original values are available in the hash referred to by $record_decoded, like so
$record_decoded->{_id}
$record_decoded->{show_image}
$record_decoded->{event}
$record_decoded->{publish_date}
$record_decoded->{data_version}
Is that what you wanted?
The object serialization documentation (particularly allow_tags) in JSON::XS may do something like what you want. Note, though, that this is not a standard JSON feature and will only work with JSON::XS.

How to find node exists in JSON

I have following JSON
{"subscription":
{
"callbackReference": "xyz" ,
"criteria": "Vote",
"destinationAddress": "3456" ,
"notificationFormat" : "JSON"
}
}
I want to check whether "notificationFormat" elements exits there using JSONPath expression. I can get the value of above element using following JSONPath expression.
$.subscription.notificationFormat
Can I use similar kind of expression which returns boolean value checking whether elements exists ?
If I understood your question correct here is an answer.
This would check if notificationFormat exists in your json.
$.subscription[?(#.notificationFormat)]
That would get all destinationAddress in case if notificationFormat exists
$.subscription[?(#.notificationFormat)].destinationAddress
ReadContext ctx = JsonPath.parse("{}", com.jayway.jsonpath.Configuration.defaultConfiguration().addOptions(Option.SUPPRESS_EXCEPTIONS));
assertThat(ctx.read("$.components"), nullValue());
If you're using Jayway's Java implementation of JSONPath - the JsonPath library - and parsing the JSON once, ahead of time, to make multiple reads more efficient, then there is an arguably clearer (than using a JSONPath filter expression) way to check whether an optional JSON property exists. Use the ReadContext object representation of the parsed JSON to return the parent JSON object as a Java HashMap, then check whether a map entry exists with the property's name. Using the JSON from the question, the (Java) code to check whether the optional 'notificationFormat' property exists would be -
ReadContext parsedJson = JsonPath.parse(jsonString);
HashMap subscription = parsedJson.read("$.subscription");
if (subscription.containsKey("notificationFormat")) {
...
}