EDIT: Whoops, forgot the config
Try to write the most efficient and concise code
Sure... for me "efficient" means "understandable" - if they wanted performance they should have said "performant" isntead :). And concise code... well, that doesn't always mean quality code, so I'll try to balance.
My approach would be to at least somewhat unify the data, then use smaller functions and deal with the super confusing data structure there.
If this was a very big project and a more generic project would actually be needed, only then would I consider making anything generic with such data. Often it's not actually necessary and just introduces a whole lot of complexity.
const payload1 = [
{
data: [
[
{
name: "Handbag",
url: "https://example.com/products/handbag",
images: {
small: "https://example.com/products/handbag/images/small.png",
medium: "https://example.com/products/handbag/images/medium.png",
large: "https://example.com/products/handbag/images/large.png",
},
color: "black",
price: "$50.00",
},
],
[
{
name: "Shoes",
url: "https://example.com/products/shoes",
images: {
small: "https://example.com/products/shoes/images/small.png",
medium: "https://example.com/products/shoes/images/medium.png",
large: "https://example.com/products/shoes/images/large.png",
},
color: "red",
price: "$35.00",
},
],
],
},
];
const payload2 = [
[
{
product_id: "000001",
meta: {
en_US: {
product_name: "Handbag",
product_urls: ["https://example.com/products/handbag"],
product_image_small: "https://example.com/products/handbag/images/small.png",
product_image_medium: "https://example.com/products/handbag/images/medium.png",
product_image_large: "https://example.com/products/handbag/images/large.png",
product_price_cents: 5000,
product_custom_attributes: {
product_price_string: "$50.00",
product_color: "black",
},
},
},
},
{
product_id: "000002",
meta: {
en_US: {
product_name: "Shoes",
product_urls: ["https://example.com/products/shoes"],
product_image_small: "https://example.com/products/shoes/images/small.png",
product_image_medium: "https://example.com/products/shoes/images/medium.png",
product_image_large: "https://example.com/products/shoes/images/large.png",
product_price_cents: 3500,
product_custom_attributes: {
product_price_string: "$35.00",
product_color: "red",
},
},
},
},
],
];
// main function
const parseProducts = (data, config) => {
const saneData = config.array ? data[0] : data[0].data;
return saneData.map(product => {
return [
{ type: 'TEXT', value: getText(product, config) }, // 'Handbag'
{ type: 'URL', value: getUrl(product, config) }, // 'https://example.com/products/handbag'
{ type: 'IMAGE', value: getImage(product, config) }, // 'https://example.com/products/handbag/images/medium.png'
{ type: 'TEXT', value: getPrice(product, config) } // '$50.00'
]
});
};
const getText = (product, config) => {
if (Array.isArray(product)) {
return product[0].name;
}
const meta = product?.meta[config.lang];
return meta?.product_name;
}
const getUrl = (product, config) => {
if (Array.isArray(product)) {
return product[0].url;
}
const meta = product?.meta[config.lang];
return meta?.product_urls[0];
}
const getImage = (product, config) => {
if (Array.isArray(product)) {
return product[0].images.medium;
}
const meta = product?.meta[config.lang];
return meta?.product_image_medium;
}
const getPrice = (product, config) => {
if (Array.isArray(product)) {
return product[0].price;
}
const meta = product?.meta[config.lang];
return meta?.product_custom_attributes.product_price_string;
}
// Test
console.log(parseProducts(payload1, { array: 0 }));
console.log(parseProducts(payload2, { array: 1, lang: "en_US" }));
Answer from Joel Peltonen on Stack OverflowVideos
That first option works fine but a nested object needs its own subquery. Here is an example on the emp/dept sample dataset. It selects from dual since the outer level is a single key that has the all rows in an array, but that can also be from a table like you're doing.
SELECT JSON_OBJECT (
KEY 'departments' VALUE (
SELECT JSON_ARRAYAGG(
JSON_OBJECT (
KEY 'department_name' VALUE d.dname,
KEY 'department_no' VALUE d.deptno,
KEY 'employees' VALUE (
SELECT JSON_ARRAYAGG (
JSON_OBJECT(
KEY 'employee_number' VALUE e.empno,
KEY 'employee_name' VALUE e.ename
)
)
FROM emp e
WHERE e.deptno = d.deptno
)
)
)
FROM dept d
)
) AS departments
FROM dual;
{
"departments": [
{
"department_name": "ACCOUNTING",
"department_no": 10,
"employees": [
{
"employee_number": 7839,
"employee_name": "KING"
},
{
"employee_number": 7782,
"employee_name": "CLARK"
},
{
"employee_number": 7934,
"employee_name": "MILLER"
}
]
},
{
"department_name": "RESEARCH",
"department_no": 20,
"employees": [
{
"employee_number": 7566,
"employee_name": "JONES"
},
{
"employee_number": 7788,
"employee_name": "SCOTT"
},
{
"employee_number": 7902,
"employee_name": "FORD"
},
{
"employee_number": 7369,
"employee_name": "SMITH"
},
{
"employee_number": 7876,
"employee_name": "ADAMS"
}
]
},
{
"department_name": "SALES",
"department_no": 30,
"employees": [
{
"employee_number": 7698,
"employee_name": "BLAKE"
},
{
"employee_number": 7499,
"employee_name": "ALLEN"
},
{
"employee_number": 7521,
"employee_name": "WARD"
},
{
"employee_number": 7654,
"employee_name": "MARTIN"
},
{
"employee_number": 7844,
"employee_name": "TURNER"
},
{
"employee_number": 7900,
"employee_name": "JAMES"
}
]
},
{
"department_name": "OPERATIONS",
"department_no": 40,
"employees": null
}
]
}
You need to use a GROUP BY clause when you have aggregated and non-aggregated columns. Given your structure you would want to use correlated sub-queries and JSON_ARRAY for the inner-most object (rather than JSON_ARRAYAGG, since you only have a single object and are not aggregating anything) :
SELECT JSON_OBJECT(
KEY 'InvoiceNumber' VALUE h.document_id,
KEY 'InvoiceCurrency' VALUE 'USD',
KEY 'InvoiceAmount' VALUE h.amount,
KEY 'InvoiceDate' VALUE h.trx_date,
KEY 'BusinessUnit' VALUE 'ABCD Corp',
KEY 'Supplier' VALUE 'NASA',
KEY 'SupplierSite' VALUE 'PHYSICAL',
KEY 'InvoiceGroup' VALUE 'MoonLander',
KEY 'Description' VALUE 'Some Description',
KEY 'invoiceLines' VALUE (
SELECT JSON_ARRAYAGG(
JSON_OBJECT(
KEY 'LineNumber' VALUE t.line_id,
KEY 'LineAmount' VALUE t.line_Value,
KEY 'invoiceDistributions' VALUE JSON_ARRAY(
JSON_OBJECT(
KEY 'DistributionLineNumber' VALUE t.line_id,
KEY 'DistributionLineType' VALUE 'Item',
KEY 'DistributionAmount' VALUE t.line_Value
)
)
)
)
FROM XXRR_LINE_STG t
WHERE t.document_id = h.document_id
)
) AS json_value
--INTO aCLOB
FROM XXRR_HDR_STG h
WHERE h.document_id = 543210;
Which, for the sample data:
CREATE TABLE xxrr_hdr_stg(document_id, amount, trx_date) AS
SELECT 543210, 100, SYSDATE FROM DUAL
CREATE TABLE xxrr_line_stg(document_id, line_id, line_value) AS
SELECT 543210, 1, 2112.75 FROM DUAL;
Outputs:
| JSON_VALUE |
|---|
| {"InvoiceNumber":543210,"InvoiceCurrency":"USD","InvoiceAmount":100,"InvoiceDate":"2023-09-05T09:07:51","BusinessUnit":"ABCD Corp","Supplier":"NASA","SupplierSite":"PHYSICAL","InvoiceGroup":"MoonLander","Description":"Some Description","invoiceLines":[{"LineNumber":1,"LineAmount":2112.75,"invoiceDistributions":[{"DistributionLineNumber":1,"DistributionLineType":"Item","DistributionAmount":2112.75}]}]} |
fiddle
Send it as raw data and set the type to application/json

To post a nested object with the key-value interface you can use a similar method to sending arrays. Pass an object key in square brackets after the object index.

"Items": [
{
"sku": "9257",
"Price": "100"
}
]
The first code is an example of Javascript code, which is similar, however not JSON. JSON would not have 1) comments and 2) the var keyword
You don't have any comments in your JSON, but you should remove the var and start like this:
Copyorders: {
The [{}] notation means "object in an array" and is not what you need everywhere. It is not an error, but it's too complicated for some purposes. AssociatedDrug should work well as an object:
Copy"associatedDrug": {
"name":"asprin",
"dose":"",
"strength":"500 mg"
}
Also, the empty object labs should be filled with something.
Other than that, your code is okay. You can either paste it into javascript, or use the JSON.parse() method, or any other parsing method (please don't use eval)
Update 2 answered:
Copyobj.problems[0].Diabetes[0].medications[0].medicationsClasses[0].className[0].associatedDrug[0].name
returns 'aspirin'. It is however better suited for foreaches everywhere
I successfully solved my problem. Here is my code:
The complex JSON object:
Copy {
"medications":[{
"aceInhibitors":[{
"name":"lisinopril",
"strength":"10 mg Tab",
"dose":"1 tab",
"route":"PO",
"sig":"daily",
"pillCount":"#90",
"refills":"Refill 3"
}],
"antianginal":[{
"name":"nitroglycerin",
"strength":"0.4 mg Sublingual Tab",
"dose":"1 tab",
"route":"SL",
"sig":"q15min PRN",
"pillCount":"#30",
"refills":"Refill 1"
}],
"anticoagulants":[{
"name":"warfarin sodium",
"strength":"3 mg Tab",
"dose":"1 tab",
"route":"PO",
"sig":"daily",
"pillCount":"#90",
"refills":"Refill 3"
}],
"betaBlocker":[{
"name":"metoprolol tartrate",
"strength":"25 mg Tab",
"dose":"1 tab",
"route":"PO",
"sig":"daily",
"pillCount":"#90",
"refills":"Refill 3"
}],
"diuretic":[{
"name":"furosemide",
"strength":"40 mg Tab",
"dose":"1 tab",
"route":"PO",
"sig":"daily",
"pillCount":"#90",
"refills":"Refill 3"
}],
"mineral":[{
"name":"potassium chloride ER",
"strength":"10 mEq Tab",
"dose":"1 tab",
"route":"PO",
"sig":"daily",
"pillCount":"#90",
"refills":"Refill 3"
}]
}
],
"labs":[{
"name":"Arterial Blood Gas",
"time":"Today",
"location":"Main Hospital Lab"
},
{
"name":"BMP",
"time":"Today",
"location":"Primary Care Clinic"
},
{
"name":"BNP",
"time":"3 Weeks",
"location":"Primary Care Clinic"
},
{
"name":"BUN",
"time":"1 Year",
"location":"Primary Care Clinic"
},
{
"name":"Cardiac Enzymes",
"time":"Today",
"location":"Primary Care Clinic"
},
{
"name":"CBC",
"time":"1 Year",
"location":"Primary Care Clinic"
},
{
"name":"Creatinine",
"time":"1 Year",
"location":"Main Hospital Lab"
},
{
"name":"Electrolyte Panel",
"time":"1 Year",
"location":"Primary Care Clinic"
},
{
"name":"Glucose",
"time":"1 Year",
"location":"Main Hospital Lab"
},
{
"name":"PT/INR",
"time":"3 Weeks",
"location":"Primary Care Clinic"
},
{
"name":"PTT",
"time":"3 Weeks",
"location":"Coumadin Clinic"
},
{
"name":"TSH",
"time":"1 Year",
"location":"Primary Care Clinic"
}
],
"imaging":[{
"name":"Chest X-Ray",
"time":"Today",
"location":"Main Hospital Radiology"
},
{
"name":"Chest X-Ray",
"time":"Today",
"location":"Main Hospital Radiology"
},
{
"name":"Chest X-Ray",
"time":"Today",
"location":"Main Hospital Radiology"
}
]
}
The jQuery code to grab the data and display it on my webpage:
Copy$(document).ready(function() {
var items = [];
$.getJSON('labOrders.json', function(json) {
$.each(json.medications, function(index, orders) {
$.each(this, function() {
$.each(this, function() {
items.push('<div class="row">'+this.name+"\t"+this.strength+"\t"+this.dose+"\t"+this.route+"\t"+this.sig+"\t"+this.pillCount+"\t"+this.refills+'</div>'+"\n");
});
});
});
$('<div>', {
"class":'loaded',
html:items.join('')
}).appendTo("body");
});
});
I found the solution:
payload = {
"access_token": "123abc",
"product_total": 2,
"product_list[0][product_id]": 111,
"product_list[1][product_id]": 222,
}
r = requests.post(url, data=payload, verify=False)
How i solved it:
I reengineered the final post request that the python function should have by opening a local port and sending the working php-request to this port in order to see its payload.
(mac terminal)
user$ nc -l localhost 11111 # to open port
POST / HTTP/1.1
Host: localhost:11111
Accept: */*
Content-Length: 115
Content-Type: application/x-www-form-urlencoded
access_token=123abc&product_total=2&product_list%5B0%5D%5Bproduct_id%5D=111&product_list%5B1%5D%5Bproduct_id%5D=22
Just have to decode the payload:
from urllib import parse
parse.unquote("access_token=123abc&product_total=2&product_list%5B0%5D%5Bproduct_id%5D=111&product_list%5B1%5D%5Bproduct_id%5D=22")
'access_token=123abc&product_total=2&product_list[0][product_id]=111&product_list[1][product_id]=22'
Now the structure of the payload is clearly visible and just have to replicate it for the python post request.
And that is how the payload looked for my initial python post request:
'access_token=123abc&product_total=2&product_list=product_id&product_list=product_id'
You can clearly see why it didn't work...
If someone has an explanation why the post request with a json-payload doesn't work - i am still very interested in that. Only idea i could come up with so far is that the API simply doesn't support a json-payload?
From the experience of previous similar questions, you should try to convert your JSON (well, actually, your Python list of dicts) in product_list to a string representation of that same JSON before posting:
import requests
import json
payload = {
"access_token": "123abc",
"product_total": 2,
"product_list": json.dumps([
{
"product_id": 111,
...
},
{
"product_id": 222,
...
}])
}
r = requests.post(url, data=payload, verify=False)
r.text