On https://jsonpath.com I have below example, using expression
$.phoneNumbers[?(#.id < 3)].number
on below JSON object.
{
"firstName": "John",
"lastName" : "doe",
"age" : 26,
"phoneNumbers": [
{
"type" : "iPhone",
"number": "0123-4567-1111",
"id": 1
},
{
"type" : "home",
"number": "0123-4567-2222",
"id": 2
},
{
"type" : "home",
"number": "0123-4567-3333",
"id": 3
}
]
}
Result is
[
"0123-4567-1111",
"0123-4567-2222"
]
Question
I only want the first string "0123-4567-1111", but appending [0] to my expression does not work. Expression $.phoneNumbers[?(#.id < 3)].number[0] gives result ["0","0"]. How can I get the first returned string?
Indeed you were very close to it by using this expression -
$.phoneNumbers[?(#.id < 3)].number[0]
In this expression you used id but in the json there is no id key so it resulted in undefined
try the expression like this using index -
$.phoneNumbers[0].number
It will return number from the first object of phoneNumbers list as : ["0123-4567-8888"]
If you want to go by conditional basis use the below expression which will return the number of type iphone -
$.phoneNumbers[?(#.type == 'iPhone')].number
Output -
["0123-4567-8888"]
Related
I have a API json response. The response has the same blocks type of data nested and i need to flatten this via the Azure datafactory. The depth of the children is variable. I'm not a expert in ADF and i couldn't find a example of how to fix this. I suspect that i need some recursive function to do this.
Some guidance would be very much appreciated.
Example json:
[
{
"id" : 1,
"name" : "item 1",
"children" : []
},
{
"id" : 2,
"name" : "item 2",
"children" : [
{
"id" : 3,
"name" : "item 3",
"children" : [
{
"id" : 4,
"name" : "item 4",
"children" : []
}
]
}
]
}
]
And i need to transform it into a sql table:
id
name
1
item 1
2
item 2
3
item 3
4
item 4
You will have to use Mapping data flow in Azure Data factory and use multiple Flatten transformations to get the desired output.
I'd like to select all elements with a certain match in the name of the property.
For example, all the properties whose name starts with 'pass' from this json:
{
"firstName": "John",
"lastName" : "doe",
"age" : 50,
"password" : "1234",
"phoneNumbers": [
{
"type" : "iPhone",
"number": "0123-4567-8888",
"password": "abcd"
},
{
"type" : "home",
"number": "0123-4567-8910",
"password": "fghi"
}
]
}
Would result something like this:
[
"1234",
"abcd",
"fghi"
]
I don't want filter by values, only by property names. Is it possible using jsonpath?
I'm using the method SelectTokens(string path) of Newtonsoft.Json.Linq
No, JSONPath defines expressions to traverse through a JSON document to reach to a subset of the JSON. It cannot be used when you don't know the exact property names.
In your case you need property values whose name starts with a specific keyword. For that, you need to traverse the whole JSON text and look for the property names which start with pass having a string type
var passwordList = new List<string>();
using (var reader = new JsonTextReader(new StringReader(jsonText)))
{
while (reader.Read())
{
if(reader.TokenType.ToString().Equals("PropertyName")
&& reader.ValueType.ToString().Equals("System.String")
&& reader.Value.ToString().StartsWith("pass"))
{
reader.Read();
passwordList.Add(reader.Value.ToString());
}
}
passwordList.ForEach(i => Console.Write("{0}\n", i));
}
I have a json document like this on my mongodb collection:
Updated document:
{
"_id" : ObjectId("59da4aef8c5d757027a5a614"),
"input" : "hi",
"output" : "Hi. How can I help you?",
"intent" : "[{\"intent\":\"greeting\",\"confidence\":0.8154089450836182}]",
"entities" : "[]",
"context" : "{\"conversation_id\":\"48181e58-dd51-405a-bb00-c875c01afa0a\",\"system\":{\"dialog_stack\":[{\"dialog_node\":\"root\"}],\"dialog_turn_counter\":1,\"dialog_request_counter\":1,\"_node_output_map\":{\"node_5_1505291032665\":[0]},\"branch_exited\":true,\"branch_exited_reason\":\"completed\"}}",
"user_id" : "50001",
"time_in" : ISODate("2017-10-08T15:57:32.000Z"),
"time_out" : ISODate("2017-10-08T15:57:35.000Z"),
"reaction" : "1"
}
I need to perform group by on intent.intent field and I'm using Rstudio with mongolite library.
What I have tried is :
pp = '[{"$unwind": "$intent"},{"$group":{"_id":"$intent.intent", "count": {"$sum":1} }}]'
stats <- chat$aggregate(
pipeline=pp,
options = '{"allowDiskUse":true}'
)
print(stats)
But it's not working, output for above code is
_id count
1 NA 727
If intent attribute type is string and keep the object as string.
We can split it to array with \" and use third item of array.
db.getCollection('test1').aggregate([
{ "$project": { intent_text : { $arrayElemAt : [ { $split: ["$intent", "\""] } ,3 ] } } },
{ "$group": {"_id": "$intent_text" , "count": {"$sum":1} }}
])
Result:
{
"_id" : "greeting",
"count" : 1.0
}
Need a JSON path expression for below JSON. I wanted to extract "Id" for each specific "name"
For Example: I need to extract "Id" : "3" for "name" : "XYZ" .
I tried a JSON path expression as $..Id which given output as:
[
"1",
"2",
"3"
]
But I needed an Id specific to "name": "XYZ"`
[
{
"primary":{
"name":"ABC"
},
"Id":"1"
},
{
"primary":{
"name":"PQR"
},
"Id":"2"
},
{
"primary":{
"name":"XYZ"
},
"Id":"3"
}
]
Able to resolve this by below expression
$..[?(#.primary.name == 'XYZ')].Id
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.