1

Background

I have created a REST endpoint in Oracle Integration Cloud that takes an id as a template parameter (ex: http://endpoint.com/api/orders/{id}), calls a stored procedure in MySQL (passing in the same id parameter) which returns data, does a transformation then returns that data as JSON in the response payload.

The tool is somewhat restrictive and it would make my life easier if the stored procedure could transform and output the query result as JSON (essentially using MySQL's new JSON_OBJECT, JSON_ARRAY, etc functions). It really just needs to be in proper JSON form (IE the actual content type of the response from MySQL doesn't matter).

I've done my best to be as thorough as possible to avoid confusion / a back and forth discussion in the comments, however if this example is two long for you skip to the last section which will likely suffice.

Outline of Current Process

The response payload has the following JSON Schema

{
  "$id": "http://example.com/example.json",
  "type": "object",
  "definitions": {},
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "results": {
      "$id": "/properties/results",
      "type": "array",
      "items": {
        "$id": "/properties/results/items",
        "type": "object",
        "properties": {
          "requestId": {
            "$id": "/properties/results/items/properties/requestId",
            "type": "string",
            "title": "The Requestid Schema ",
            "default": "",
            "examples": [
              "id"
            ]
          },
          "invoiceNumber": {
            "$id": "/properties/results/items/properties/invoiceNumber",
            "type": "string",
            "title": "The Invoicenumber Schema ",
            "default": "",
            "examples": [
              "129"
            ]
          },
          "orderNumber": {
            "$id": "/properties/results/items/properties/orderNumber",
            "type": "string",
            "title": "The Ordernumber Schema ",
            "default": "",
            "examples": [
              "13"
            ]
          }
        }
      }
    }
  }
}

Here is an example response payload

{
  "results": [
    {
      "requestId": "2018-CRD-1818",
      "invoiceNumber": "120129",
      "orderNumber": "1343"
    },
    {
      "requestId": "2018-RMA-1891",
      "invoiceNumber": "1291234
      "orderNumber": "1323"
    }
  ]
}

Currently, I have a stored procedure that basically condenses multiple rows into a single, comma separated row and then returns the result to Oracle's Integration Cloud.

 DELIMITER //
 CREATE PROCEDURE GetOrderNumbers(IN id int, OUT ids varchar(4000))
   BEGIN

        SELECT 
                group_concat(concat(crd.requestId, ',', crd.originalOrderNumber))
            FROM 
                LathamCR_CreditRequest crd
            WHERE 
                crd.originalOrderNumber = id
            UNION ALL
            SELECT 
                rma.requestId
            FROM 
                LathamCR_RMARequest rma
            WHERE 
                rma.originalOrderNumber = id
            LIMIT 1
        INTO ids;
    END //
DELIMITER ;

Then in OIC I break transform that csv into the aforementioned JSON and return it.

New Process and Question

As stated before, instead of returning a single row CSV from the stored procedure I want to return a JSON Object (essentially doing the transformation in MySQL). So the stored procedure signature would be as follows

 DELIMITER //
 CREATE PROCEDURE GetOrderNumbers(IN id int, OUT ids JSON)
   BEGIN

         # The SQL Transformation

    END //
DELIMITER ;

The issue I'm having is that I cannot seem to condense multiple rows into a single JSON Object. I can condense every row into a JSON Object using the following:

SELECT
    JSON_OBJECT('requestId',crd.requestId, 'invoiceNumber', crd.originalOrderInvoice, 'orderNumber', crd.originalOrderNumber)
FROM 
    LathamCR_CreditRequest crd
UNION ALL
SELECT 
    JSON_OBJECT('requestId',rma.requestId, 'invoiceNumber', rma.originalOrderInvoice, 'orderNumber', rma.originalOrderNumber)
FROM
    LathamCR_RMARequest rma;

This returns the following result set (where each new line is a row).

# results
'{\"requestId\": \"2015-CRD-0000001\", \"orderNumber\": \"35454\", \"invoiceNumber\": \"3654654\"}'
'{\"requestId\": \"2015-CRD-0000002\", \"orderNumber\": \"4343434\", \"invoiceNumber\": \"3243434\"}'
'{\"requestId\": \"2015-CRD-0000003\", \"orderNumber\": \"3423423\", \"invoiceNumber\": \"2342342\"}'
'{\"requestId\": \"2015-CRD-0000004\", \"orderNumber\": \"3543543\", \"invoiceNumber\": \"9766483\"}'
'{\"requestId\": \"2015-CRD-0000005\", \"orderNumber\": \"8754632\", \"invoiceNumber\": \"**77732\"}'

This is exactly what I want, except I want to return all of that in one row as an array inside a parent object. For example:

{ 
   "results": [
      {"requestId": "2015-CRD-0000005", "orderNumber": "8754632", "invoiceNumber": "**77732"}, 
      {"requestId": "2016-CRD-0000005", "orderNumber": "866632", "invoiceNumber": "*6732"}
    ]
}

So to attempt to get it in one row I used GROUP_CONCAT and JSON_ARRAY as follows:

SELECT
    GROUP_CONCAT(
        JSON_ARRAY (
            JSON_OBJECT('requestId',crd.requestId, 'invoiceNumber', crd.originalOrderInvoice, 'orderNumber', crd.originalOrderNumber)
        )
    ) as result
FROM 
    LathamCR_CreditRequest crd
UNION ALL
SELECT 
    GROUP_CONCAT(
        JSON_ARRAY (
            JSON_OBJECT('requestId',rma.requestId, 'invoiceNumber', rma.createdDate, 'orderNumber', rma.originalOrderNumber)
        )
    ) as result
FROM
    LathamCR_RMARequest rma;

This is very close but it returns two rows (union all essentially stops working) and also I still need to wrap the array in a parent JSON Object. When I try to use JSON_OBJECT as the outer most block it then treats the array like a string (and I still can't get the union all to work again).

1 Answer 1

2

One option is to use JSON_MERGE()(deprecated 5.7.22) --> JSON_MERGE_PATCH() / JSON_MERGE_PRESERVE(), see 12.16.1 JSON Function Reference.

SET @`json_LathamCR_CreditRequest` :=
  (SELECT
     CONCAT(
       '[',
       GROUP_CONCAT(
         JSON_OBJECT('requestId', `requestId`)
       ),
       ']')
  FROM `LathamCR_CreditRequest`);

SET @`json_LathamCR_RMARequest` :=
  (SELECT
     CONCAT(
       '[',
       GROUP_CONCAT(
         JSON_OBJECT('requestId', `requestId`)
       ),
       ']')
  FROM `LathamCR_RMARequest`);

SELECT
  `der`.`result`,
  JSON_VALID(`der`.`result`) `JSON_VALID?`
FROM (
  SELECT
    JSON_OBJECT(
      'results',
      JSON_MERGE(@`json_LathamCR_CreditRequest`,
                 @`json_LathamCR_RMARequest`
      )
  ) `result`
) `der`;

See db-fiddle.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.