I have FB analytics configured for iOS and android app. It does recognize iOS platform when viewing events correctly. But for android it only qualifies it as android about 30% of all.
Here's how those events are shown in FB analytics debugging screen: ('inne wartości' stands for 'other')
I wonder how FB does the recognition? By advertising id? Read docs through but didn't find info about this anywhere.
Here's a FB response that gets recognized as android: (obfuscated few details):
{
"req": {
"method": "POST",
"url": "https://graph.facebook.com/v2.6/000000000/activities",
"data": {
"advertiser_id": "2e9ab235-84c0-4b22-8421-xxxxxxxxxxxxx",
"advertiser_tracking_enabled": 1,
"application_tracking_enabled": 1,
"bundle_id": "com.myapp",
"bundle_short_version": "1.7.0",
"event": "CUSTOM_APP_EVENTS",
"custom_events": [
{
"_appVersion": "1.7.0",
"_eventName": "App Launched",
"_logTime": 1476295031,
"fb_currency": "USD"
}
]
},
"headers": {
"user-agent": "Segment.io/1.0",
"content-type": "application/json"
}
},
"header": {
"access-control-allow-origin": "*",
"pragma": "no-cache",
"cache-control": "private, no-cache, no-store, must-revalidate",
"facebook-api-version": "v2.6",
"expires": "Sat, 01 Jan 2000 00:00:00 GMT",
"content-type": "text/javascript; charset=UTF-8",
"x-fb-trace-id": "BH4kXNYDDL+",
"x-fb-rev": "2617769",
"x-fb-debug": "eNcBCpuFfVirTkclVvZ0WeYh60r+2tBIqg6lKPCrWNtGASVULq6jrVwQxqYulMUyCI3ZaBhZRQ64xdxdXOQg2w==",
"date": "Wed, 12 Oct 2016 17:57:24 GMT",
"connection": "close",
"content-length": "16"
},
"status": 200,
"text": "{\"success\":true}"
}
And this one is not recognized as android:
{
"req": {
"method": "POST",
"url": "https://graph.facebook.com/v2.6/000000000000/activities",
"data": {
"advertiser_id": "88697a4d-f658-41d3-84db-xxxxxxxxxx",
"advertiser_tracking_enabled": 1,
"application_tracking_enabled": 1,
"bundle_id": "com.myapp",
"bundle_short_version": "1.7.0",
"event": "CUSTOM_APP_EVENTS",
"custom_events": [
{
"_appVersion": "1.7.0",
"_eventName": "App Launched",
"_logTime": 1476206487,
"fb_currency": "USD"
}
]
},
"headers": {
"user-agent": "Segment.io/1.0",
"content-type": "application/json"
}
},
"header": {
"access-control-allow-origin": "*",
"pragma": "no-cache",
"cache-control": "private, no-cache, no-store, must-revalidate",
"facebook-api-version": "v2.6",
"expires": "Sat, 01 Jan 2000 00:00:00 GMT",
"content-type": "text/javascript; charset=UTF-8",
"x-fb-trace-id": "AqASb9qsUSx",
"x-fb-rev": "2613995",
"x-fb-debug": "aDLUDoC+7vmlVY28UsEtusYgzdkmxK8qVrn4gCo29ovLw9Us27Gh/Iy1163dfTDF5rKg/JWiv3xsfq3hugijlg==",
"date": "Tue, 11 Oct 2016 17:21:37 GMT",
"connection": "close",
"content-length": "16"
},
"status": 200,
"text": "{\"success\":true}"
}
I can't see any interesting changes that that would point to an android platform.
Update
As advised by Ramkumar, I tried posting events with FB sdk and it indeed worked. I'd really like to keep using segment, so keeping this as solution is not possible in my app.
I wonder what's missing from the params that segment sends to FB. Is this because of session_id which is in there when using FB SDK but is absent in segment request? See gist with dump from adb logcat when using FB SDK
From your post, it looks like you are using segment.io to send events to our servers. If you use the FB SDK to send events you will not see this problem - could you please give that a try?
Related
I am sending a request from a Nuxt3 SSR app (test.example.com) to a custom strapi endpoint (test-backend.example.com)
I'm making the call from Nuxt3 like this from app.vue
<script setup>
import { useStore } from '#/stores/index'
let data = reactive({})
[data] = await Promise.all([
useFetch(`${useRuntimeConfig().API_URL}api/debug`),
])
store.setApiData(data.data)
</script>
To hit this custom strapi endpoint at /api/debug
module.exports = {
async debug(ctx, next) {
ctx.body = {
ctx: ctx,
reqOrigin: ctx.request.origin,
}
}
};
Reading the request headers using ctx.request.origin returns the backend host and not the frontend host.
"ctx": {
"request": {
"method": "GET",
"url": "/api/debug",
"header": {
"host": "test-backend.example.com",
"x-real-ip": "203.96.140.24",
"x-forwarded-for": "203.96.140.24",
"connection": "close",
"cache-control": "no-cache",
"postman-token": "946f9d5f-b9b6-4dc0-a52b-95fd84b81de8",
"user-agent": "PostmanRuntime/7.6.0",
"accept": "*/*",
"accept-encoding": "gzip, deflate"
}
},
"response": {
"status": 200,
"message": "OK",
"header": {
"content-security-policy": "connect-src 'self' https:;img-src 'self' data: blob:;media-src 'self' data: blob:;default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline'",
"x-dns-prefetch-control": "off",
"expect-ct": "max-age=0",
"x-frame-options": "SAMEORIGIN",
"strict-transport-security": "max-age=31536000; includeSubDomains",
"x-download-options": "noopen",
"x-content-type-options": "nosniff",
"x-permitted-cross-domain-policies": "none",
"referrer-policy": "no-referrer",
"vary": "Origin",
"content-type": "application/json; charset=utf-8",
"x-powered-by": "Strapi <strapi.io>"
}
},
"app": {
"subdomainOffset": 2,
"proxy": false,
"env": "production"
},
"originalUrl": "/api/debug",
"req": "<original node req>",
"res": "<original node res>",
"socket": "<original node socket>"
},
"reqOrigin": "http://test-backend.example.com"
Logging ctx on the backend shows that ctx.request.header.host is test-backend.example.com. I was expecting host to be text.example.com where the fetch originated from. Not the host to which the request was being sent.
How do I get the request host and not the servers host?
Why does changing the maxResults parameter cause the resultSizeEstimate to drastically change when calling gmail.users.messages.list()?
The Google API docs lists resultSizeEstimate as: Estimated total number of results.
... which means this final result set should not change just by altering the number of items returned per page.
Example A: maxResults: 1 ... resultSizeEstimate: 8
{
"config": {
"url": "https://www.googleapis.com/gmail/v1/users/me/messages?q=before%3A2021%2F1%2F9&maxResults=1",
"method": "GET",
"headers": {
"Accept-Encoding": "gzip",
"User-Agent": "google-api-nodejs-client/0.7.2 (gzip)",
"Authorization": "Bearer [snip]",
"Accept": "application/json"
},
"params": {
"q": "before:2021/1/9",
"maxResults": 1
},
"responseType": "json"
},
"data": {
"messages": [ ... ],
"nextPageToken": "14911817971227869758",
"resultSizeEstimate": 8
},
"headers": {
"alt-svc": "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\"",
"cache-control": "private",
"connection": "close",
"content-encoding": "gzip",
"content-type": "application/json; charset=UTF-8",
"date": "Sun, 09 Jan 2022 12:59:48 GMT",
"server": "ESF",
"transfer-encoding": "chunked",
"vary": "Origin, X-Origin, Referer",
"x-content-type-options": "nosniff",
"x-frame-options": "SAMEORIGIN",
"x-xss-protection": "0"
},
"status": 200,
"statusText": "OK"
}
Example B: maxResults: 2 ... resultSizeEstimate: 12
{
"config": {
"url": "https://www.googleapis.com/gmail/v1/users/me/messages?q=before%3A2021%2F1%2F9&maxResults=2",
"method": "GET",
"headers": {
"Accept-Encoding": "gzip",
"User-Agent": "google-api-nodejs-client/0.7.2 (gzip)",
"Authorization": "Bearer [snip]",
"Accept": "application/json"
},
"params": {
"q": "before:2021/1/9",
"maxResults": 2
},
"responseType": "json"
},
"data": {
"messages": [ ... ],
"nextPageToken": "16903415066875011466",
"resultSizeEstimate": 12
},
"headers": {
"alt-svc": "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\"",
"cache-control": "private",
"connection": "close",
"content-encoding": "gzip",
"content-type": "application/json; charset=UTF-8",
"date": "Sun, 09 Jan 2022 13:10:48 GMT",
"server": "ESF",
"transfer-encoding": "chunked",
"vary": "Origin, X-Origin, Referer",
"x-content-type-options": "nosniff",
"x-frame-options": "SAMEORIGIN",
"x-xss-protection": "0"
},
"status": 200,
"statusText": "OK"
}
Example C: maxResults: (not set) ... resultSizeEstimate: 412
{
"config": {
"url": "https://www.googleapis.com/gmail/v1/users/me/messages?q=before%3A2021%2F1%2F9",
"method": "GET",
"headers": {
"Accept-Encoding": "gzip",
"User-Agent": "google-api-nodejs-client/0.7.2 (gzip)",
"Authorization": "Bearer [snip]",
"Accept": "application/json"
},
"params": {
"q": "before:2021/1/9"
},
"responseType": "json"
},
"data": {
"messages": [ ... ],
"nextPageToken": "16942818266524948378",
"resultSizeEstimate": 412
},
"headers": {
"alt-svc": "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\"",
"cache-control": "private",
"connection": "close",
"content-encoding": "gzip",
"content-type": "application/json; charset=UTF-8",
"date": "Sun, 09 Jan 2022 13:09:05 GMT",
"server": "ESF",
"transfer-encoding": "chunked",
"vary": "Origin, X-Origin, Referer",
"x-content-type-options": "nosniff",
"x-frame-options": "SAMEORIGIN",
"x-xss-protection": "0"
},
"status": 200,
"statusText": "OK"
}
This was previously reported in Issue Tracker and was considered to be intended behavior by Google, since resultSizeEstimate is not expected to be exact; it's an "estimate":
the reason why resultSizeEstimate shows differents values is due to its estimation. As mentioned in the documentation resultSizeEstimate is just an estimated total number of results but not the exact number of results.
Reference:
users.messages.list method returns different amount of messages when using “maxResults” parameter
I try to send an API request with cy.request but there seems to be something wrong with the data format. My code looks as follows:
cy.request({
url: Cypress.env("RtmApiUrl") + "/test-plan/",
method: "POST",
headers: {
"Authorization": "Bearer " + Cypress.env('RtmApiToken'),
"content-type": "application/json",
body: {
"projectKey": "QAIR",
"summary": "API Test Regression",
"description": "Full regression",
"parentTestKey": "F-QAIR-TP-8",
"priority": {
"id": 3,
"name": "Medium"
},
"status": {
"id": 10005,
"name": "Backlog"
},
"includedTestCases": []
},
},
});
And the console output from Cypress Test Runner:
CypressError: `cy.request()` failed on:
https://rtm-api.hexygen.com/api/test-plan/
The response we received from your web server was:
> 400: Bad Request
This was considered a failure because the status code was not `2xx` or `3xx`.
If you do not want status codes to cause failures pass the option: `failOnStatusCode: false`
-----------------------------------------------------------
The request we sent was:
Method: POST
URL: https://rtm-api.hexygen.com/api/test-plan/
Headers: {
"Connection": "keep-alive",
"Authorization": "Bearer <some Token>",
"content-type": "application/json",
"body": {
"projectKey": "QAIR",
"summary": "API Test Regression",
"description": "Full regression",
"parentTestKey": "F-QAIR-TP-8",
"priority": {
"id": 3,
"name": "Medium"
},
"status": {
"id": 10005,
"name": "Backlog"
},
"includedTestCases": []
},
"user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36",
"accept": "*/*",
"accept-encoding": "gzip, deflate",
"content-length": 0
}
-----------------------------------------------------------
The response we got was:
Status: 400 - Bad Request
Headers: {
"server": "Cowboy",
"connection": "keep-alive",
"x-content-type-options": "nosniff",
"x-xss-protection": "1; mode=block",
"cache-control": "no-cache, no-store, max-age=0, must-revalidate",
"pragma": "no-cache",
"expires": "0",
"strict-transport-security": "max-age=31536000 ; includeSubDomains",
"x-frame-options": "DENY",
"content-type": "application/json",
"content-length": "69",
"date": "Tue, 13 Jul 2021 07:32:36 GMT",
"via": "1.1 vegur"
}
Body: {
"errorMessages": [
"No content to map to Object due to end of input"
]
}
I already tried the same combination of header and body with Postman and curl and it worked. Is there something I missed?
Any help is appreciated. Thanks in advance.
Folks, I missed a bracket at the end of the headers block. So this was a real classic layer 8 issue...
cy.request({
url: Cypress.env("RtmApiUrl") + "/test-plan/",
method: "POST",
headers: {
"Authorization": "Bearer " + Cypress.env('RtmApiToken'),
"content-type": "application/json"
},
body: {
"projectKey": "QAIR",
"summary": "API Test Regression",
"description": "Full regression",
"parentTestKey": "F-QAIR-TP-8",
"priority": {
"id": 3,
"name": "Medium"
},
"status": {
"id": 10005,
"name": "Backlog"
},
"includedTestCases": []
},
},
});
My setup looks like this:
|––––––––––––| |–––––––––––––| |–––––––––––––––––|
| | <- origin 1 -> | API Gateway | <-> | Lambda function |
| | |–––––––––––––| |–––––––––––––––––|
| CloudFront |
| | |–––––––––––––|
| | <- origin 2 -> | S3 bucket |
|––––––––––––| |–––––––––––––|
I need CloudFront in front of the API Gateway to get automatic http->https redirection.
I'm using a custom login.example.com subdomain w/ CloudFront.
API Gateway's generated URL is the origin 1 for CloudFront distribution.
This all works as expected.
I can even return one Set-Cookie header from the lambda function and it will get passed on until it reaches the browser.
{
"statusCode": 302,
"body": "",
"headers": {
"location": "/test",
"surrogate-control": "no-store",
"cache-control": "no-store, no-cache, must-revalidate, proxy-revalidate",
"pragma": "no-cache",
"expires": "0",
"content-length": "0",
"date": "Fri, 19 Feb 2021 17:25:56 GMT",
"connection": "keep-alive",
"set-cookie": "cookie1=68abcdbefbef7d84c26e68; Max-Age=2592000; Domain=example.com; Path=/; HttpOnly; Secure; SameSite=Strict"
},
"isBase64Encoded": false
}
Adding another one isn't working - as expected when you look at the docs:
https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#apigateway-multivalue-headers-and-parameters
https://aws.amazon.com/blogs/compute/support-for-multi-value-parameters-in-amazon-api-gateway/
{
"statusCode": 302,
"headers": {
"location": "/test",
"set-cookie": [
"cookie1=68abcdbefbef7d84c26e68; Max-Age=2592000; Domain=example.com; Path=/; HttpOnly; Secure; SameSite=Strict",
"cookie2-login=; Max-Age=0; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Secure"
],
"surrogate-control": "no-store",
"cache-control": "no-store, no-cache, must-revalidate, proxy-revalidate",
"pragma": "no-cache",
"expires": "0",
"content-length": "0"
}
}
Both of these will be ignored/removed.
But even when I'm using the multiValueHeaders object to return more than one of the same kind like this:
{
"statusCode": 302,
"body": "",
"headers": {
"location": "/test",
"surrogate-control": "no-store",
"cache-control": "no-store, no-cache, must-revalidate, proxy-revalidate",
"pragma": "no-cache",
"expires": "0",
"content-length": "0",
"date": "Fri, 19 Feb 2021 17:25:56 GMT",
"connection": "keep-alive"
},
"isBase64Encoded": false,
"multiValueHeaders": {
"Set-Cookie": [
"cookie1=68abcdbefbef7d84c26e68; Max-Age=2592000; Domain=example.com; Path=/; HttpOnly; Secure; SameSite=Strict",
"cookie2-login=; Max-Age=0; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Secure"
]
}
}
the API Gateway removes/ignores them from the response it passes on to CloudFront.
What am I doing wrong?
Do I have to map something in the API Gateway when using the multiValueHeaders?
Normal headers['set-cookie'] is passed on automatically but multiValueHeaders not?
Are the additional attributes a problem?
Is it a problem that I'm trying to set the cookie for the root-domain and not the login.example.com domain?
Not sure how Philipp missed this, as it was on the same page he cited:
To customize the response, your Lambda function should return a response with the following format.
{
"cookies" : ["cookie1", "cookie2"],
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headername": "headervalue", ... },
"body": "Hello from Lambda!"
}
So just return cookies: ['name=value', 'name=value']
Source: https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.v2
Finally found the answer myself:
The new payload format (2.0) does not support multiValueHeaders.
Working with AWS Lambda proxy integrations for HTTP APIs
[...] Format 2.0 doesn't have multiValueHeaders or multiValueQueryStringParameters fields. Duplicate headers are combined with commas and included in the headers field. Duplicate query strings are combined with commas and included in the queryStringParameters field. [...]
https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html
So I'm rewriting the set-cookie headers to different spellings:
Set-cookie
sEt-cookie
seT-cookie
That was the way you had to do it before there were multiValueHeaders - but it seems it is still the only when you're using the new payload format :(
I'm using the Group Nodes in App Connect ACE 11 to call a service multiple times and trying to aggregate the the responses. Everything works fine and the below is the result of InputRoot.ComIbmGroupCompleteNode.Group.
{
"msg": {
"GroupProperties": {
"GroupId": "010000000000000000000000000000001000000000000000",
"GroupName": "TSTGRP",
"GroupCreationTime": 1593669682652,
"GroupCommitTime": 1593669682707,
"GroupCompleteTime": 1593669682806,
"GroupOutputTime": 1593669682806,
"GroupStatus": "Completed"
},
"Context": {
"HTTP": {
"RequestIdentifier": "45564854000000000e000000db851d0ecc11000000000000"
},
"RouterList": {}
},
"Replies": {
"FLDR": {
"ReplyId": "534f41503000000067e55223146300000400000000000000",
"RequestSendTime": 1593669682674,
"ReplyReceiptTime": 1593669682706,
"Reply": {
"Root": {
"HTTPResponseHeader": {
"X-Original-HTTP-Status-Line": "HTTP/1.1 200 OK",
"X-Original-HTTP-Status-Code": 200,
"Date": "Thu, 02 Jul 2020 06:01:17 GMT",
"Content-Type": "application/json; charset=utf-8",
"Content-Length": "83",
"Connection": "keep-alive",
"Set-Cookie": "__cfduid=dfbd2cc294d944ed4cfdf6b72a343f8dc1593669677; expires=Sat, 01-Aug-20 06:01:17 GMT; path=/; domain=.typicode.com; HttpOnly; SameSite=Lax",
"X-Powered-By": "Express",
"X-Ratelimit-Limit": "10000",
"X-Ratelimit-Remaining": "9999",
"X-Ratelimit-Reset": "1592660247",
"Vary": "Origin, Accept-Encoding",
"Access-Control-Allow-Credentials": "true",
"Cache-Control": "max-age=43200",
"Pragma": "no-cache",
"Expires": "-1",
"X-Content-Type-Options": "nosniff",
"Etag": "W/\"53-hfEnumeNh6YirfjyjaujcOPPT+s\"",
"Via": "1.1 vegur",
"CF-Cache-Status": "HIT",
"Age": "15242",
"Accept-Ranges": "bytes",
"cf-request-id": "03afb689ec00007f11da290200000001",
"Server": "cloudflare",
"CF-RAY": "5ac626bcaa097f11-CMB"
},
"JSON": {
"Data": {
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
}
}
}
}
},
"FLDR": {
"ReplyId": "534f415031000000273b5323146300000400000000000000",
"RequestSendTime": 1593669682707,
"ReplyReceiptTime": 1593669682737,
"Reply": {
"Root": {
"HTTPResponseHeader": {
"X-Original-HTTP-Status-Line": "HTTP/1.1 200 OK",
"X-Original-HTTP-Status-Code": 200,
"Date": "Thu, 02 Jul 2020 06:01:17 GMT",
"Content-Type": "application/json; charset=utf-8",
"Content-Length": "99",
"Connection": "keep-alive",
"Set-Cookie": "__cfduid=debd2bf084ee690942fb5d3439e41fa331593669677; expires=Sat, 01-Aug-20 06:01:17 GMT; path=/; domain=.typicode.com; HttpOnly; SameSite=Lax",
"X-Powered-By": "Express",
"X-Ratelimit-Limit": "500",
"X-Ratelimit-Remaining": "497",
"X-Ratelimit-Reset": "1593684076",
"Vary": "Origin, Accept-Encoding",
"Access-Control-Allow-Credentials": "true",
"Cache-Control": "max-age=43200",
"Pragma": "no-cache",
"Expires": "-1",
"X-Content-Type-Options": "nosniff",
"Etag": "W/\"63-+s0zIP5ZEQN9hypVJUneLybJ+L0\"",
"Via": "1.1 vegur",
"CF-Cache-Status": "HIT",
"Age": "8713",
"Accept-Ranges": "bytes",
"cf-request-id": "03afb68a0900007f29ad07c200000001",
"Server": "cloudflare",
"CF-RAY": "5ac626bcdc137f29-CMB"
},
"JSON": {
"Data": {
"userId": 1,
"id": 2,
"title": "quis ut nam facilis et officia qui",
"completed": false
}
}
}
}
},
"FLDR": {
"ReplyId": "534f4150320000000bbb5323146300000400000000000000",
"RequestSendTime": 1593669682707,
"ReplyReceiptTime": 1593669682737,
"Reply": {
"Root": {
"HTTPResponseHeader": {
"X-Original-HTTP-Status-Line": "HTTP/1.1 200 OK",
"X-Original-HTTP-Status-Code": 200,
"Date": "Thu, 02 Jul 2020 06:01:17 GMT",
"Content-Type": "application/json; charset=utf-8",
"Content-Length": "84",
"Connection": "keep-alive",
"Set-Cookie": "__cfduid=dfbd2cc294d944ed4cfdf6b72a343f8dc1593669677; expires=Sat, 01-Aug-20 06:01:17 GMT; path=/; domain=.typicode.com; HttpOnly; SameSite=Lax",
"X-Powered-By": "Express",
"X-Ratelimit-Limit": "500",
"X-Ratelimit-Remaining": "499",
"X-Ratelimit-Reset": "1593684076",
"Vary": "Origin, Accept-Encoding",
"Access-Control-Allow-Credentials": "true",
"Cache-Control": "max-age=43200",
"Pragma": "no-cache",
"Expires": "-1",
"X-Content-Type-Options": "nosniff",
"Etag": "W/\"54-J3JtLgWuXjgj1OZdyAcKAqOaKHo\"",
"Via": "1.1 vegur",
"CF-Cache-Status": "HIT",
"Age": "8713",
"Accept-Ranges": "bytes",
"cf-request-id": "03afb68a0c00007f11da291200000001",
"Server": "cloudflare",
"CF-RAY": "5ac626bcea187f11-CMB"
},
"JSON": {
"Data": {
"userId": 1,
"id": 3,
"title": "fugiat veniam minus",
"completed": false
}
}
}
}
}
}
}
}
My question is how can I access the 3 JSON.Data elements and create a combined response. I know this is not a valid JSON and FLDR is a repeating key. Also this is not an array. How can I access these elements and create a combined response like this?
{
"result1": {
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
},
"result2": {
"userId": 1,
"id": 2,
"title": "quis ut nam facilis et officia qui",
"completed": false
},
"result3": {
"userId": 1,
"id": 3,
"title": "fugiat veniam minus",
"completed": false
}
}
Any help would be very much appreciated.
If you have a message tree containing that structure then you can access any part of it - regardless of whether it would be a valid JSON document.
Have you tried writing a normal FOR loop in ESQL to iterate over the occurrences of FLDR?
Note: this code is completely un-tested and probably contains syntax errors and defects...
DECLARE index INTEGER 1;
FOR refFLDR AS InputRoot.ComIbmGroupCompleteNode.Group.msg.Replies.FLDR[] DO
DECLARE fieldName 'Result' || index;
CREATE LASTCHILD OF OutputRoot.JSON.Data TYPE Name NAME fieldName FROM refFLDR;
SET index = index + 1;
END FOR;