Create ODBC wrapper/driver for REST API - json

just checking before i build the wheel
I need a hackjob to present an api endpoint in a database. It doesn't need to do anything fancy, just convert what the rest api spits out into a single column of json. A new row at each iteration at the root/top level would be nice but a single varchar or whatever would be ok too
Does an ODBC wrapper exist out there anywhere? Googling just brings up hits for doing the opposite (exposing databases as an api). I'm not interested in the simba etc paid stuff. The consumer is SQL server so i can just use xp_cmdshell with curl as a last resort
so for instance the output of this : http://jsonapiplayground.reyesoft.com/v2/authors could come out as a table like so (a row for each author)
|data |
---------------------------------------------------
|{
"type": "authors",
"id": "1",
"attributes": {
"name": "Madge Mohr DVM 2",
"date_of_birth": "1977-08-21",
"date_of_death": "2009-09-14"
},
"relationships": {
"photos": {
"data": []
},
"books": {
"data": [
{
"type": "books",
"id": "41"
}
]
}
},
"links": {
"self": "/v2/authors/1"
}
} |
---------------------------------------------------
|{
"type": "authors",
"id": "3",
"attributes": {
"name": "Zelma Ortiz DDS",
"date_of_birth": "1992-09-06",
"date_of_death": "2000-12-19"
},
"relationships": {
"photos": {
"data": [
{
"type": "photos",
"id": "3"
}
]
},
"books": {
"data": [
{
"type": "books",
"id": "36"
},
{
"type": "books",
"id": "48"
}
]
}
},
"links": {
"self": "/v2/authors/3"
}
}|
----------
|{
"type": "authors",
"id": "4",
"attributes": {
"name": "Fermin Barrows Sr.",
"date_of_birth": "1991-03-18",
"date_of_death": "1975-11-07"
},
"relationships": {
"photos": {
"data": [
{
"type": "photos",
"id": "4"
}
]
},
"books": {
"data": [
{
"type": "books",
"id": "1"
},
{
"type": "books",
"id": "26"
},
{
"type": "books",
"id": "44"
},
{
"type": "books",
"id": "46"
}
]
}
},
"links": {
"self": "/v2/authors/4"
}
}|
----------
|{
"type": "authors",
"id": "5",
"attributes": {
"name": "Terry Durgan",
"date_of_birth": "2011-03-06",
"date_of_death": "2017-04-13"
},
"relationships": {
"photos": {
"data": [
{
"type": "photos",
"id": "5"
}
]
},
"books": {
"data": [
{
"type": "books",
"id": "6"
},
{
"type": "books",
"id": "16"
},
{
"type": "books",
"id": "50"
}
]
}
},
"links": {
"self": "/v2/authors/5"
}
}|
----------
|{
"type": "authors",
"id": "6",
"attributes": {
"name": "Annalise Walsh",
"date_of_birth": "2004-11-27",
"date_of_death": "1997-07-20"
},
"relationships": {
"photos": {
"data": [
{
"type": "photos",
"id": "6"
}
]
},
"books": {
"data": [
{
"type": "books",
"id": "4"
},
{
"type": "books",
"id": "5"
},
{
"type": "books",
"id": "21"
}
]
}
},
"links": {
"self": "/v2/authors/6"
}
}|
---------

Related

Get JSON value based on the value in a sub-node

The following JSON payload is attached to the Webhook when someone submits a form.
{
"event_id": "01G9HND6HYK185YMA9Z5CZ3BV0",
"event_type": "form_response",
"form_response": {
"form_id": "cvjMXer8",
"token": "01G9HND6HYK185YMA9Z5CZ3BV0",
"landed_at": "2022-08-03T10:53:16Z",
"submitted_at": "2022-08-03T10:53:16Z",
"definition": {
"id": "cvjMXer8",
"title": "My Test Form",
"fields": [
{
"id": "AfpCiPiAmHjD",
"ref": "01G76Q8G8SWQMYAD3T4SWCBEQ4",
"type": "opinion_scale",
"title": "Hur nöjd är du?",
"properties": {}
},
{
"id": "KQlkSr1mg6ge",
"ref": "966e1df9-e9a5-4243-80f7-c0db86f2b705",
"type": "short_text",
"title": "Skriv vad du tycker",
"properties": {}
},
{
"id": "LGTRVpqJ5cOy",
"ref": "03278ed7-f602-465d-b7ec-667d486f937a",
"type": "multiple_choice",
"title": "Välj ett nummer mellan 1 och 4",
"properties": {},
"choices": [
{
"id": "wcwXgizdXJFQ",
"label": "1"
},
{
"id": "lTzi4WiQjEuo",
"label": "2"
},
{
"id": "uq6kPQTEutof",
"label": "3"
},
{
"id": "FI0JDCaXBaZE",
"label": "4"
}
]
}
]
},
"answers": [
{
"type": "number",
"number": 42,
"field": {
"id": "AfpCiPiAmHjD",
"type": "opinion_scale",
"ref": "01G76Q8G8SWQMYAD3T4SWCBEQ4"
}
},
{
"type": "text",
"text": "Lorem ipsum dolor",
"field": {
"id": "KQlkSr1mg6ge",
"type": "short_text",
"ref": "966e1df9-e9a5-4243-80f7-c0db86f2b705"
}
},
{
"type": "choice",
"choice": {
"label": "Barcelona"
},
"field": {
"id": "LGTRVpqJ5cOy",
"type": "multiple_choice",
"ref": "03278ed7-f602-465d-b7ec-667d486f937a"
}
}
]
}
}
The answers are inside the node form_response.answers. As we see, there are three answers posted, each with a somewhat different structure based on the type of question. To collect the correct value, I should first look at the field.id to know which question this answer corresponds to.
E.g. If field.id = "AfpCiPiAmHjD" then I know I should pick up the value 42 from its parent node.
What value should I write in a Power Automate flow to fetch this value using a Variable step?

extract collection from json based on a condition using logic app

I am trying to Extract and sum a particular value using group by from json collection in azure logic app. Trying to achieve this by applying "Condition" connector. My Json file looks like below:
"Release": [
{
"O_Id": "D_13211175",
"R_ID": "D_132111751",
"Res": [
{
"A_Id": "32323222",
"F_Qty": 1,
"I_Id": "828929",
"OL_Id": "1",
"Qty": 1,
"RL_Id": "1",
"Unique_Identifier": "5970703818904601622__1",
},
{
"A_Id": "32323223",
"F_Qty": 1,
"I_Id": "828929",
"OL_Id": "1",
"Qty": 1,
"RL_Id": "1",
"Unique_Identifier": "5970703818904692717__1",
},
]
}
]
I want to calculate the sum of Qty group by I_Id from array Res using logic app connector "Condition".
Note: As Res is an array, there can be repetition I_Id with same value, hence, the requirement to get the Qty count based on I_Id
There are few ways to achieve your requirement but here is one of the workaround that worked when reproduced from our end.
Firstly, I have initialised a temporary integer variable to iterated inside the "Res" Array using Until Loop by checking the length of "Res" using the below expression.
length(body('Parse_JSON')?['Release']?[0]?['Res'])
Inside Until I have used condition action to check if I_Id is same using the below expression to the left.
body('Parse_JSON')?['Release']?[0]?['Res']?[variables('temp')]?['I_Id']
and below expression to the right
body('Parse_JSON')?['Release']?[0]?['Res']?[add(variables('temp'),1)]?['I_Id']
Then if the condition satisfies I'm adding the Qty using the expression as below.
add(body('Parse_JSON')?['Release']?[0]?['Res']?[variables('temp')]?['Qty'],body('Parse_JSON')?['Release']?[0]?['Res']?[add(variables('temp'),1)]?['Qty'])
Here is the flow of my logic app
[Optional step]
Considering the bigger picture, I have initialzed another variable quantity and added the resultant of Compose 4 to Qty variable
RESULTS:
Considering the below sample JSON
{
"Release": [
{
"O_Id": "D_13211175",
"R_ID": "D_132111751",
"Res": [
{
"A_Id": "32323222",
"F_Qty": 1,
"I_Id": "828929",
"OL_Id": "1",
"Qty": 1,
"RL_Id": "1",
"Unique_Identifier": "5970703818904601622__1"
},
{
"A_Id": "32323223",
"F_Qty": 1,
"I_Id": "828929",
"OL_Id": "1",
"Qty": 1,
"RL_Id": "1",
"Unique_Identifier": "5970703818904692717__1"
},
{
"A_Id": "32323223",
"F_Qty": 1,
"I_Id": "828929",
"OL_Id": "1",
"Qty": 5,
"RL_Id": "1",
"Unique_Identifier": "5970703818904692717__1"
}
]
}
]
}
Here is the result
To avoid confusion try the below code view in your resource
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Compose": {
"inputs": {
"Release": [
{
"O_Id": "D_13211175",
"R_ID": "D_132111751",
"Res": [
{
"A_Id": "32323222",
"F_Qty": 1,
"I_Id": "828929",
"OL_Id": "1",
"Qty": 1,
"RL_Id": "1",
"Unique_Identifier": "5970703818904601622__1"
},
{
"A_Id": "32323223",
"F_Qty": 1,
"I_Id": "828929",
"OL_Id": "1",
"Qty": 1,
"RL_Id": "1",
"Unique_Identifier": "5970703818904692717__1"
},
{
"A_Id": "32323223",
"F_Qty": 1,
"I_Id": "828929",
"OL_Id": "1",
"Qty": 5,
"RL_Id": "1",
"Unique_Identifier": "5970703818904692717__1"
}
]
}
]
},
"runAfter": {},
"type": "Compose"
},
"Compose_3": {
"inputs": "#variables('Qty')",
"runAfter": {
"Until": [
"Succeeded"
]
},
"type": "Compose"
},
"Initialize_variable": {
"inputs": {
"variables": [
{
"name": "temp",
"type": "integer",
"value": 0
}
]
},
"runAfter": {
"Parse_JSON": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Initialize_variable_2": {
"inputs": {
"variables": [
{
"name": "Qty",
"type": "integer",
"value": 0
}
]
},
"runAfter": {
"Initialize_variable": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Parse_JSON": {
"inputs": {
"content": "#outputs('Compose')",
"schema": {
"properties": {
"Release": {
"items": {
"properties": {
"O_Id": {
"type": "string"
},
"R_ID": {
"type": "string"
},
"Res": {
"items": {
"properties": {
"A_Id": {
"type": "string"
},
"F_Qty": {
"type": "integer"
},
"I_Id": {
"type": "string"
},
"OL_Id": {
"type": "string"
},
"Qty": {
"type": "integer"
},
"RL_Id": {
"type": "string"
},
"Unique_Identifier": {
"type": "string"
}
},
"required": [
"A_Id",
"F_Qty",
"I_Id",
"OL_Id",
"Qty",
"RL_Id",
"Unique_Identifier"
],
"type": "object"
},
"type": "array"
}
},
"required": [
"O_Id",
"R_ID",
"Res"
],
"type": "object"
},
"type": "array"
}
},
"type": "object"
}
},
"runAfter": {
"Compose": [
"Succeeded"
]
},
"type": "ParseJson"
},
"Until": {
"actions": {
"Condition": {
"actions": {
"Compose_2": {
"inputs": "#add(outputs('Compose_4'),variables('Qty'))",
"runAfter": {
"Compose_4": [
"Succeeded"
]
},
"type": "Compose"
},
"Compose_4": {
"inputs": "#add(body('Parse_JSON')?['Release']?[0]?['Res']?[variables('temp')]?['Qty'],body('Parse_JSON')?['Release']?[0]?['Res']?[add(variables('temp'),1)]?['Qty'])",
"runAfter": {},
"type": "Compose"
},
"Set_variable": {
"inputs": {
"name": "Qty",
"value": "#outputs('Compose_2')"
},
"runAfter": {
"Compose_2": [
"Succeeded"
]
},
"type": "SetVariable"
}
},
"expression": {
"and": [
{
"equals": [
"#body('Parse_JSON')?['Release']?[0]?['Res']?[variables('temp')]?['I_Id']",
"#body('Parse_JSON')?['Release']?[0]?['Res']?[add(variables('temp'),1)]?['I_Id']"
]
}
]
},
"runAfter": {},
"type": "If"
},
"Increment_variable": {
"inputs": {
"name": "temp",
"value": 1
},
"runAfter": {
"Condition": [
"Succeeded"
]
},
"type": "IncrementVariable"
}
},
"expression": "#equals(variables('temp'), length(body('Parse_JSON')?['Release']?[0]?['Res']))",
"limit": {
"count": 60,
"timeout": "PT1H"
},
"runAfter": {
"Initialize_variable_2": [
"Succeeded"
]
},
"type": "Until"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {},
"triggers": {
"manual": {
"inputs": {
"schema": {}
},
"kind": "Http",
"type": "Request"
}
}
},
"parameters": {}
}

Dependent field in another dependent field

I have a form with dependent fields that works fine, but now I'm trying to add a second dependent field, that will rely on my first dependent field:
{
"job_level": {
"type": "select",
"label": "Job Level",
"order": 8,
"state": "required",
"selection_values": [
{
"id": "",
"label": "* Job Level"
},
{
"id": "c_level",
"label": "C-Level"
},
{
"id": "architect",
"label": "Architect"
}
]
},
"job_function": {
"type": "select",
"label": "Job Function",
"order": 9,
"state": "required",
"dependent_field": {
"name": "job_level",
"values": [
"c_level",
"architect"
]
},
"selection_values": {
"c_level": [
{
"id": "",
"label": "* Job Function"
},
{
"id": "Security",
"label": "Security"
},
{
"id": "HR",
"label": "HR"
}
],
"architect": [
{
"id": "",
"label": "* Job Function"
},
{
"id": "Sales",
"label": "Sales"
}
]
}
},
"job_role": {
"type": "select",
"label": "Job Role",
"order": 10,
"state": "required",
"dependent_field": {
"name": "job_function",
"values": [
"Security",
"HR",
"Sales"
]
},
"selection_values": {
"Security": [
{
"id": "",
"label": "* Job Role"
},
{
"id": "CISO",
"label": "CISO"
},
{
"id": "CSO",
"label": "CSO"
},
{
"id": "Other",
"label": "Other"
}
],
"HR": [
{
"id": "",
"label": "* Job Role"
},
{
"id": "CHRO",
"label": "CHRO"
},
{
"id": "Other",
"label": "Other"
}
],
"Sales": [
{
"id": "",
"label": "* Job Role"
},
{
"id": "Operations_Sales",
"label": "Operations/Sales"
},
{
"id": "Other",
"label": "Other"
}
]
}
}
}
job_role is the field I'm trying to add, but when I'm selecting a Job Function in the form, the field is not appearing in the form. Any thoughts? Thanks.

Kubernetes + jq - retrieving containers list per pod yields cartesian product

Im trying to use jq on kubernetes json output, to create new json object containing list of objects - container and image per pod, however im getting cartesian product.
my input data (truncated from sensitive info):
{
"apiVersion": "v1",
"items": [
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"creationTimestamp": "2021-06-30T12:45:40Z",
"name": "pod-1",
"namespace": "default",
"resourceVersion": "757679286",
"selfLink": "/api/v1/namespaces/default/pods/pod-1"
},
"spec": {
"containers": [
{
"image": "image-1",
"imagePullPolicy": "Always",
"name": "container-1",
"resources": {},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File",
"volumeMounts": [
{
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
"readOnly": true
}
]
},
{
"image": "image-2",
"imagePullPolicy": "Always",
"name": "container-2",
"resources": {},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File",
"volumeMounts": [
{
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
"readOnly": true
}
]
}
],
"dnsPolicy": "ClusterFirst",
"enableServiceLinks": true,
"priority": 0,
"restartPolicy": "Always",
"schedulerName": "default-scheduler",
"securityContext": {},
"serviceAccount": "default",
"serviceAccountName": "default",
"terminationGracePeriodSeconds": 30,
"tolerations": [
{
"effect": "NoExecute",
"key": "node.kubernetes.io/not-ready",
"operator": "Exists",
"tolerationSeconds": 300
},
{
"effect": "NoExecute",
"key": "node.kubernetes.io/unreachable",
"operator": "Exists",
"tolerationSeconds": 300
}
],
"volumes": [
{
"name": "default-token-b954f",
"secret": {
"defaultMode": 420,
"secretName": "default-token-b954f"
}
}
]
},
"status": {
"conditions": [
{
"lastProbeTime": null,
"lastTransitionTime": "2021-06-30T12:45:40Z",
"status": "True",
"type": "Initialized"
},
{
"lastProbeTime": null,
"lastTransitionTime": "2021-06-30T12:45:40Z",
"message": "containers with unready status: [container-1 container-2]",
"reason": "ContainersNotReady",
"status": "False",
"type": "Ready"
},
{
"lastProbeTime": null,
"lastTransitionTime": "2021-06-30T12:45:40Z",
"message": "containers with unready status: [container-1 container-2]",
"reason": "ContainersNotReady",
"status": "False",
"type": "ContainersReady"
},
{
"lastProbeTime": null,
"lastTransitionTime": "2021-06-30T12:45:40Z",
"status": "True",
"type": "PodScheduled"
}
],
"containerStatuses": [
{
"image": "image-1",
"imageID": "",
"lastState": {},
"name": "container-1",
"ready": false,
"restartCount": 0,
"started": false,
"state": {
"waiting": {
"message": "Back-off pulling image \"image-1\"",
"reason": "ImagePullBackOff"
}
}
},
{
"image": "image-2",
"imageID": "",
"lastState": {},
"name": "container-2",
"ready": false,
"restartCount": 0,
"started": false,
"state": {
"waiting": {
"message": "Back-off pulling image \"image-2\"",
"reason": "ImagePullBackOff"
}
}
}
],
"qosClass": "BestEffort",
"startTime": "2021-06-30T12:45:40Z"
}
}
],
"kind": "List",
"metadata": {
"resourceVersion": "",
"selfLink": ""
}
}
my command:
jq '.items[] | { "name": .metadata.name, "containers": [{ "name": .spec.containers[].name, "image": .spec.containers[].image }]} '
desired output:
{
"name": "pod_1",
"containers": [
{
"name": "container_1",
"image": "image_1"
},
{
"name": "container_2",
"image": "image_2"
}
]
}
output I get:
{
"name": "pod-1",
"containers": [
{
"name": "container-1",
"image": "image-1"
},
{
"name": "container-1",
"image": "image-2"
},
{
"name": "container-2",
"image": "image-1"
},
{
"name": "container-2",
"image": "image-2"
}
]
}
Could anyone explain what am I doing wrong?
Best Regards, Piotr.
The problem is "name": .spec.containers[].name and "image": .spec.containers[].image:
Both expressions generate a sequence of each value for name and image which will than be combined.
Simplified example of why you get a Cartesian product:
jq -c -n '{name: ("A", "B"), value: ("C", "D")}'
outputs:
{"name":"A","value":"C"}
{"name":"A","value":"D"}
{"name":"B","value":"C"}
{"name":"B","value":"D"}
You get the desired output using this jq filter on your input:
jq '
.items[]
| {
"name": .metadata.name,
"containers": .spec.containers
| map({name, image})
}'
output:
{
"name": "pod-1",
"containers": [
{
"name": "container-1",
"image": "image-1"
},
{
"name": "container-2",
"image": "image-2"
}
]
}

Converting array to objects within an object

I have been battling with this for sometime, ive looked a few articles in regards to this topic. I can't seem to get exactly what I'm aiming for. I have this original json data that I would like to transform a bit.
Group the objects based on the label.env (for now only using one env), then inserting those objects from the original json into an object named projects.
orginial_json
{
"createTime": "2020-06-25T14:16:45.720Z",
"labels": {
"cb_domain": "cloud-services",
"cb_product": "infra",
"env": "prod",
"owner": "cloud-server"
},
"lifecycleState": "ACTIVE",
"name": "projectname",
"parent": {
"id": "123456577",
"type": "folder"
},
"projectId": "projectname-324234",
"projectNumber": "962363417856"
}
{
"createTime": "2020-06-24T19:45:42.851Z",
"labels": {
"cb_domain": "cloud-services",
"cb_product": "ad",
"env": "prod",
"owner": "cloud-server"
},
"lifecycleState": "ACTIVE",
"name": "projectname2",
"parent": {
"id": "4352564765437",
"type": "folder"
},
"projectId": "projectname2-4567",
"projectNumber": "3243456324"
}
Im using jq -s 'group_by(.labels.env) | .[] | { (.[0].labels.env) : { projects: .[] | . } }'
to nest the original json data into objects grouped by env\projects, which works but seems to duplicate it instead of putting each object within projects.
{
"prod": {
"projects": {
"createTime": "2020-06-25T14:16:45.720Z",
"labels": {
"cb_domain": "cloud-services",
"cb_product": "infra",
"env": "prod",
"owner": "cloud-server"
},
"lifecycleState": "ACTIVE",
"name": "projectname",
"parent": {
"id": "770593713153",
"type": "folder"
},
"projectId": "projectname-324234",
"projectNumber": "962363417856"
}
}
}
{
"prod": {
"projects": {
"createTime": "2020-06-24T19:45:42.851Z",
"labels": {
"cb_domain": "cloud-services",
"cb_product": "ad",
"env": "prod",
"owner": "cloud-server"
},
"lifecycleState": "ACTIVE",
"name": "projectname2",
"parent": {
"id": "4352564765437",
"type": "folder"
},
"projectId": "projectname2-4567",
"projectNumber": "3243456324"
}
}
}
What I'm aiming for is
{
"prod": {
"projects": {
"createTime": "2020-06-25T14:16:45.720Z",
"labels": {
"cb_domain": "cloud-services",
"cb_product": "infra",
"env": "prod",
"owner": "cloud-server"
},
"lifecycleState": "ACTIVE",
"name": "projectname",
"parent": {
"id": "770593713153",
"type": "folder"
},
"projectId": "projectname-324234",
"projectNumber": "962363417856"
},
{
"createTime": "2020-06-24T19:45:42.851Z",
"labels": {
"cb_domain": "cloud-services",
"cb_product": "ad",
"env": "prod",
"owner": "cloud-server"
},
"lifecycleState": "ACTIVE",
"name": "projectname2",
"parent": {
"id": "4352564765437",
"type": "folder"
},
"projectId": "projectname2-4567",
"projectNumber": "3243456324"
}
}
}
Allowing for some minor discrepancies in the Q, the following variant of your jq program seems to do what you're trying to achieve:
group_by(.labels.env)
| .[]
| .[0].labels.env as $key
| { ($key) : { projects: . } }