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 Overflow
🌐
Medium
samedesilva.medium.com › how-to-create-a-nested-json-object-payload-with-an-array-using-java-map-and-pass-it-as-the-payload-2aa0611fa2b3
How to create a Nested JSON Object payload and pass it as the payload of Playwright Java API post request. | by Sameera De Silva | Medium
December 13, 2023 - package com.payloads; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; public class CreatedNestedJSONObjectPayloadUsingJavaMapWithArray { public static void main(String[] args) { // Create a Gson instance Gson gson = new Gson(); // Create the main JSON object JsonObject mainJsonObjectPayload = new JsonObject(); // Add properties to the main JSON object since id doesn't have child can add directly. mainJsonObjectPayload.addProperty("id", 0); // Create and add the nested "category" JSON object since category has two children as id,name JsonObject categoryObject = new JsonObject(); categoryObject.addProperty("id", 0); categoryObject.addProperty("name", "string"); //After that add category to main object as a simple key and value.
Top answer
1 of 1
1

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" }));

🌐
QA Automation Expert
qaautomation.expert › tag › nested-json-payload
Nested JSON Payload – QA Automation Expert
So, we will split this into small parts or objects. So basically, we can split the above JSON into 4 parts – Employee, Contractors, CompanyPFDetails, and NestedPOJODemo. companyName, companyEmailId, companyNumber, and companyAddress are 1:1 mapping in the payload.
🌐
JDELIST
jdelist.com › home › forums › jd edwards® enterprise one / one world discussions › jd edwards® orchestrator
E9.2 - Create nested multi-level JSON payload | JDELIST.com - JD Edwards ERP Forums
April 23, 2024 - **Data Loading**: Load the input JSON into a Python dictionary. 2. **Data Structure Preparation**: Create a template for the output JSON based on the structure you provided.
🌐
Adobe
opensource.adobe.com › Spry › samples › data_region › JSONDataSetSample.html
JSON Data Set Sample
Doing that with the data set used in Example 10 would require some JavaScript logic embedded in spry attribute conditionals to control when things showed up. A simpler approach would be to use NestedJSONDataSets. In this example we use the same JSON data used in Example 10, but we will use 2 nested JSON data sets to track the "batter" and "topping" data.
Find elsewhere
🌐
EasyMorph Community
community.easymorph.com › t › post-request-with-nested-json-body-how-can-i-generate-it › 2933
POST Request with nested JSON Body - how can I generate it? - EasyMorph Community - Data preparation professionals and enthusiasts
July 30, 2021 - Hello, I'm trying to send data through a JSON Body, however I think that the API receiving the data is expecting a nested JSON, with the text "inputs" in the first level, and the inputs themselves in the second level: More details: https://developer.salesforce.com/docs/atlas.en-us.api_action.meta/api_action/actions_obj_custom_notification.htm So in EasyMorph, I created the following action: However, here I can't include the first JSON level ("inputs"). At the moment this is an "Iterate...
🌐
ReqBin
reqbin.com › req › 2xhbguy8 › json-payload-example
How do I send JSON Payload to the server?
... POST /echo/post/json HTTP/1.1 Host: reqbin.com Accept: application/json Content-Type: application/json Content-Length: 52 { "Id": 78912, "Quantity": 1, "Price": 18.00 } ... JavaScript Object Notation (JSON) is a standard text format for ...
Top answer
1 of 2
2

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
    }
  ]
}
2 of 2
0

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

🌐
IBM
ibm.com › docs › en › db2 › 11.5.x
JSON nested objects
Objects can be nested inside other objects. Each nested object must have a unique access path.
🌐
Postman
community.postman.com › help hub
How can I target nested objects from a JSON data file? - Help Hub - Postman Community
December 12, 2017 - Given I have the below JSON data file [ { "email": "test@test.com", "address": { "addressLine1": "123 Fake Street", "county": "Something", "postcode": "BA11 4PM" } } ] And I want to use the data file in my POST body each iteration (I know, I ...
🌐
GitHub
github.com › strongloop › loopback-next › issues › 5611
How do I validate a nested JSON api request body payload using ...
April 2, 2020 - I am trying to validate a nested JSON payload using models in loopback4. Loopback4 is able to validate the name and description property. However, it isn't validating the contact.type or contact.number property. This is an example of wha...
Published   May 30, 2020
Author   vishwas097
Top answer
1 of 2
3

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?

2 of 2
1

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
🌐
Stack Overflow
stackoverflow.com › questions › 73783039 › keep-nested-object-in-a-json-payload-without-modeling-it-with-gson
java - Keep nested object in a JSON payload without modeling it with GSON - Stack Overflow
Example: public class MyDomain { int id; JSonGenericObject payload; } Still I need the payload reference because at the end the full object must be transmitted to the remote caller which started the procedure ... Does this JSON data appear nested inside the complete JSON document?