Retriving child nodes from JSON response in PowerShell - powershell

{
"completionTime": 1477067415024,
"context": {
"environmentId": 78
},
"id": 51,
"jobId": 473,
"jobName": "Ravindra",
"reportIds": [
959
],
"startTime": 1477067357196,
"status": "PASSED",
"username": "svc.soaess"
}
from this json structure I have to get the value 959.
$response.ChildNodes.reportIds displays blank. Tried with array etc. no luck.

Presumably $response is a string, so you need to convert it to an object first, before you can access the object's properties.
($response | ConvertFrom-Json).reportIds

Related

How to properly pass the session_id to GA4 via Measurement protocol

GA4 purchase events are sent from client server via measurement protocol. But there is no session_id parameter in the queries, because of that source and medium is lost. We tried to pass the session_id parameter in MP request, but no data were received.
Example of submitted request:
{
"timestamp_micros": "1664522406546590",
"non_personalized_ads": false,
"events": [
{
"name": "purchase_balance_top_up",
"params": {
"user_id": "11111111",
"crm_id": "11111111",
"balance": 990,
"payment_method": "paymore"
}
}
],
"client_id": "1119492379.1652295143",
"session_id": "1664522264",
"user_id": "11111111"
}
Attaching a screenshot of the raw data from BigQuery on events sent by MP.
Screenshot of the raw data from BigQuery
Help, how to properly pass the session_id? Or how to make sure that events don't lose source param?
We found a solution to the problem. It's simple. The parameter "session_id" must be passed inside the array "params" of the event.
Here is an example of the correct event data array to be sent via measurement protocol:
{
"timestamp_micros": "1664522406546590",
"non_personalized_ads": false,
"events": [
{
"name": "purchase_balance_top_up",
"params": {
"user_id": "11111111",
"crm_id": "11111111",
"balance": 990,
"payment_method": "paymore",
"session_id": "1664522264"
}
}
],
"client_id": "1119492379.1652295143",
"user_id": "11111111"
}
Actually we are sending purchase events similarly with such request:
{
"client_id": "xxx.xxx",
"user_id" : "xxxx",
"non_personalized_ads": false,
"user_properties": {
"user_id_dimension": {
"value": "xxxx"
}
},
"events": [{
"name": "purchase",
"params": {
"currency": "USD",
"transaction_id": "T_12345",
"value": 12.21,
"engagement_time_msec": 10,
"session_id": "XXXXXXXXXX",
"items": [
{
"item_name": "Top-up"
}
]
}
}]
}
but we are not sending timestamp_micros. And we send 'user_id_dimension' as user property with the same value as 'user_id' parameter to observe user id further in Exploration reports. We've created user-scoped custom dimension in GA4 interface with dimension name User ID and this user property 'user_id_dimension'. Everything works

How to create a jsonpath to instagram business account in a batch request with the Graph API?

My goal is to create a batch request with dependent calls as documented here:
https://developers.facebook.com/docs/graph-api/making-multiple-requests#operations
You can reference the results of a previous operation using JSONPath in form post parameters in addition to query string parameters.
I can't get the right JSONPath to make it work when there are multiple elements in the data array that have an instagram_business_account.id (iba_id)
The two calls that I want to make are
/me/accounts?fields=instagram_business_account
/17841400714813297?fields=business_discovery.username(thomasguntenaar){media_count}
my batch looks like
[
{"method":"GET","name":"get-ig", "relative_url":"me/accounts?fields=instagram_business_account"},
{"method":"GET", "relative_url":"{result=get-ig:$.data..instagram_business_account.id}?fields=business_discovery.username(thomasguntenaar){media_count}}"}
]
in the second query you are supposed to put the JSONPath to the instagram business account id
after result=
I get this error back
{
"code": 404,
"body": "{
\"error\": {
\"message\": \"(#803) Some of the aliases you requested do not exist: 17841400714813297,17841403388404550,17841401383243593\",
\"type\": \"OAuthException\",
\"code\": 803,
\"fbtrace_id\": \"FV8qA+oA7fp\"
}
}"
}
Facebooks json response after the first call is
{
"data": [
{
"id": "466912700123917"
},
{
"id": "502655553273897"
},
{
"instagram_business_account": {
"id": "17841400714813297"
},
"id": "503124266815195"
},
{
"instagram_business_account": {
"id": "17841403388404550"
},
"id": "510613645695833"
},
{
"instagram_business_account": {
"id": "17841401383243593"
},
"id": "2061834074114937"
}
],
"paging": {
"cursors": {
"before": "NDY2OTEyNzAwMTIzOTE3",
"after": "MjA2MTgzNDA3NDExNDkzNwZDZD"
}
}
}
When you query the second request like this
?ids=17841400714813297,17841403388404550,17841401383243593&fields=business_discovery.username(thomasguntenaar){username,media_count}
the response looks like this
{
"17841400714813297": {
"business_discovery": {
"username": "thomasguntenaar",
"media_count": 76,
"id": "17841400714813297"
},
"id": "17841400714813297"
},
"17841403388404550": {
"business_discovery": {
"username": "thomasguntenaar",
"media_count": 76,
"id": "17841400714813297"
},
"id": "17841403388404550"
},
"17841401383243593": {
"business_discovery": {
"username": "thomasguntenaar",
"media_count": 76,
"id": "17841400714813297"
},
"id": "17841401383243593"
}
}
(#803) Some of the aliases you requested do not exist: 17841400714813297,17841403388404550,17841401383243593
Apparently the API thinks this was supposed to be one id, and doesn’t realize it is supposed to be three separate ones.
The API has a syntax to request data for more than one object in one request - instead of /{id}?fields=foo, you can make a request of the form ?ids={1,2,3}&fields=foo, to request this data for the objects with ids 1, 2 and 3 in one go. The resulting data structure will contain a sub-structure for each of those ids.
The same structure should work in batch requests as well, when parts (here, the IG account ids returned by the previous query) are dynamically inserted.

How to append web request results in a while loop

I need to call an API and loop through the various pages of results that are returned and append them all to one object.
I've tried the code below. Generally += works when appending to a powershell object, but no luck this time.
Note: URI and Get are both functions that are defined elsewhere. They work as expected elsewhere in the code.
$min=1
$max=2
while ($min -le $max){
$url= URI "tasks?page=$min"
$x=Get $url
if($min=1){
$response=$x
}
else{
$response+=$x
}
$min=$min+1
}
sample response (converted to json):
"value": [
{
"task_id": 17709655,
"project_id": 1928619,
"start_date": "2019-04-11",
"end_date": "2019-11-29",
"start_time": null,
"hours": 1.5,
"people_id": 17083963,
"status": 2,
"priority": 0,
"name": "",
"notes": "",
"repeat_state": 0,
"repeat_end_date": null,
"created_by": 331791,
"modified_by": 0,
"created": "2019-04-12 00:39:30.162",
"modified": "2019-04-12 00:39:30.162",
"ext_calendar_id": null,
"ext_calendar_event_id": null,
"ext_calendar_recur_id": null
},
{
"task_id": 17697564,
"project_id": 1928613,
"start_date": "2019-10-08",
"end_date": "2019-10-08",
"start_time": null,
"hours": 8,
"people_id": 17083966,
"status": 2,
"priority": 0,
"name": "",
"notes": "",
"repeat_state": 0,
"repeat_end_date": null,
"created_by": 327507,
"modified_by": 0,
"created": "2019-04-11 16:10:22.969",
"modified": "2019-04-11 16:10:22.969",
"ext_calendar_id": null,
"ext_calendar_event_id": null,
"ext_calendar_recur_id": null
}
],
"Count": 2
}```
Assuming you want the output to be an array, I'd write your code like this:
$min=1
$max=2
$response = foreach ($Page in $min..$max) {
$url = URI "tasks?page=$Page"
Get $url
}
This is the generally preferred method, because both Strings and Arrays have fixed lengths in .Net and therefore PowerShell.
Here, $response[0] should be the first response, $response[1] the second, etc.
If the above doesn't work for you, then my first guess would be that the output of Get isn't a string.
If you're expecting $response to be a single valid JSON string containing all the responses, then my response is "JSON doesn't work that way." You'll have to parse each JSON response to objects (hint: ConvertFrom-Json) combine them, and then possibly convert them back to JSON (ConvertTo-Json). Note that .Net's native dialect of JSON doesn't match the rest of the Internet's dialect of JSON, particularly with dates (though it looks like your dates here are strings). You may want to use JSON.Net, which I believe does match the common Internet dialect.
You may be able to combine $response like this:
$CombinedResponse = '[' + ($response -join ',') + ']'
But I don't know how well that's going to work if you then try to parse that as JSON.

Does the OData protocol provide a way to transform an array of objects to an array of raw values?

Is there a way specify in an OData query that instead of certain name/value pairs being returned, a raw array should be returned instead? For example, if I have an OData query that results in the following:
{
"#odata.context": "http://blah.org/MyService/$metadata#People",
"value": [
{
"Name": "Joe Smith",
"Age": 55,
"Employers": [
{
"Name": "Acme",
"StartDate": "1/1/1990"
},
{
"Name": "Enron",
"StartDate": "1/1/1995"
},
{
"Name": "Amazon",
"StartDate": "1/1/1999"
}
]
},
{
"Name": "Jane Doe",
"Age": 30,
"Employers": [
{
"Name": "Joe's Crab Shack",
"StartDate": "1/1/2007"
},
{
"Name": "TGI Fridays",
"StartDate": "1/1/2010"
}
]
}
]
}
Is there anything I can add to the query to instead get back:
{
"#odata.context": "http://blah.org/MyService/$metadata#People",
"value": [
{
"Name": "Joe Smith",
"Age": 55,
"Employers": [
[ "Acme", "1/1/1990" ],
[ "Enron", "1/1/1995" ],
[ "Amazon", "1/1/1999" ]
]
},
{
"Name": "Jane Doe",
"Age": 30,
"Employers": [
[ "Joe's Crab Shack", "1/1/2007" ],
[ "TGI Fridays", "1/1/2010" ]
]
}
]
}
While I could obviously do the transformation client side, in my use case the field names are very large compared to the data, and I would rather not transmit all those names over the wire nor spend the CPU cycles on the client doing the transformation. Before I come up with my own custom parameters to indicate that the format should be as I desire, I wanted to check if there wasn't already a standardized way to do so.
OData provides several options to control the amount of data and metadata to be included in the response.
In OData v4, you can add odata.metadata=minimal to the Accept header parameters (check the documentation here). This is the default behaviour but even with this, it will still include the field names in the response and for a good reason.
I can see why you want to send only the values without the fields name but keep in mind that this will change the semantic meaning of the response structure. It will make it less intuitive to deal with as a json record on the client side.
So to answer your question, The answer is 'NO',
Other options to minimize the response size:
You can use the $value OData option to gets the raw value of a single property.
Check this example:
services.odata.org/OData/OData.svc/Categories(1)/Products(1)/Supplier/Address/City/$value
You can also use the $select option to cherry pick only the fields you need by selecting a subset of properties to include in the response

page-id/notifications returns an empty array

I'm writing a desktop application using Facebook SDK .NET. This app must do somethink for every post, comment or message sent to a Facebook page. I'm using the page-id/notifications API command:
page-id/notifications?fields=id,title,unread,application,from,message,object&limit=250
This command returns correct unseen count in summary section but data array is empty:
{
"data": [
],
"summary": {
"unseen_count": 2,
"updated_time": "2016-02-05T14:53:10+0000"
}
}
If someone write a new wall post on the page or send a private message to the page, unseen_count is updated but data array is always empty. If someoune write a comment to an exisiting wall post unseen_count is updates and data array is populated with a comment notification (only this type of notification are added to data array):
{
"data": [
{
"id": "notif_XXXXXXXXXXXXXXX_XXXXXXXXXXXXXXXX",
"title": "yyyyy yyyyyyy commented on his post.",
"unread": 1,
"application": {
"link": "https://www.facebook.com/games/?app_id=xxxxxxxxxxx",
"name": "Feed Comments",
"id": "1967xxxxxxx"
},
"from": {
"name": "Mxxxx Sxxxxxx",
"id": "1020xxxxxxxxxxxxx"
},
"object": {
"created_time": "2016-02-05T14:52:32+0000",
"message": "ABCDEFGHILMNOPQRSTUVZ",
"id": "36xxxxxxxxxxxx0_546xxxxxxxxxxx0"
},
"to": {
"name": "Ixxxxxxx",
"id": "36xxxxxxxxxxxxx"
}
}
],
"paging": {
"previous": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
"next": "xxxxxxxxxxxxxxxxxxxx
},
"summary": {
"unseen_count": 3,
"updated_time": "2016-02-05T14:55:23+0000"
}
}
Is it an API bug or there is something wrong in my API request?
I CANNOT use real time notification.
Thanks
Marco