OpenEdge ABL JSON to temp table: READ-JSON

227 Views Asked by At

How can I READ-JSON this (below) into temp table :

{
  "args": {
  },
  "data": "{\"name\":\"morpheus11\",\"job\":\"leader1221\"}",
  "files": {
  },
  "form": {
  },
  "headers": {
    "Accept": "application\/json",
    "Content-Length": "40",
    "Content-Type": "application\/json",
    "Host": "httpbin.org",
    "User-Agent": "OpenEdge-HttpClient\/0.4.0 (UNIX\/64) OpenEdge\/99.2.99.0.9999 Lib-ABLSockets\/0.5.0",
    "X-Amzn-Trace-Id": "Root=1-9999998e-0e281713363302e331999999"
  },
  "json": {
    "job": "leader1221",
    "name": "morpheus11"
  },
  "origin": "888.53.150.88",
  "url": "https:\/\/httpbin.org\/post"
}

This is what I have written so far. Right now the export stream dOut1 does not produce anything. My guess is that I don't have all the table specify... DO I need to define all json node like: Args, Data, Files, Headers, Origin and URL? Thank you for your help

  def temp-table tt serialize-name 'json'
   field job  as char 
   field name as char.
  def dataset args for tt.

  def var dURL         as char          no-undo init "https://httpbin.org/post".
  def var dRequest     as IHttpRequest  no-undo.
  def var dResponse    as IHttpResponse no-undo.
  def var dClient      as IHttpClient   no-undo.
  def var dRequestResp as longchar      no-undo.  
  def var dJson        as JsonObject    no-undo. /* used by outbound Json and the return inbound Json */
  
  dClient = ClientBuilder:Build():Client.
  dJson   = new JsonObject() .
  dJson:Add("name","morpheus11").
  dJson:Add("job","leader1221").

  dRequest  = RequestBuilder:Post(dURL,dJson)
                    :ContentType('application/json')
                    :AcceptJson()
                    :Request.
  dResponse = dClient:Execute(dRequest).
  
  if dResponse:StatusCode <> 200 then do:
    message subst("dResponse:StatusCode = &1", dResponse:StatusCode).
  end. 
  else do:
    dJson = cast(dResponse:Entity, JsonObject).
    dJson:Write(dRequestResp, true).
    
    dataset args:read-json("longchar",dRequestResp).
    for each tt on error undo, return error on stop undo, return error:
      export stream dOut1 delimiter "|"
        tt.
    end. 
    output stream dOut1 close.
  end.

Thank you

1

There are 1 best solutions below

3
Mike Fechner On BEST ANSWER

The JSON does not match a ProDataset. ProDatasets are represented by JSON objects with a nested JSON array per temp-table.

But you can read the "json" object directly into the temp-table's tt default-buffer:

dJson = cast(dResponse:Entity, JsonObject).
dJson = dJson:GetJsonObject ("json") .
dJson:Write(dRequestResp, true).
buffer tt:read-json("longchar",dRequestResp).

and a further optimization: No need to use the longchar as an intermediate:

dJson = cast(dResponse:Entity, JsonObject).
dJson = dJson:GetJsonObject ("json") .
buffer tt:read-json("JsonObject", dJson).

Here's my comlete sample:

/*------------------------------------------------------------------------
    File        : json.p
    Purpose     :

    Syntax      :

    Description :

    Author(s)   : mikef
    Created     : Sun Jan 07 16:08:47 CET 2024
    Notes       :

https://stackoverflow.com/questions/77766521/openedge-abl-json-to-temp-table-read-json

  ----------------------------------------------------------------------*/

/* ***************************  Definitions  ************************** */

BLOCK-LEVEL ON ERROR UNDO, THROW.

USING Consultingwerk.Util.* FROM PROPATH.
using Progress.Json.ObjectModel.* from propath.
using OpenEdge.Net.HTTP.* from propath.

/* ***************************  Main Block  *************************** */

  def temp-table tt serialize-name 'json'
   field job  as char
   field name as char.
  def dataset args for tt.

  def var dURL         as char          no-undo init "https://httpbin.org/post".
  def var dRequest     as IHttpRequest  no-undo.
  def var dResponse    as IHttpResponse no-undo.
  def var dClient      as IHttpClient   no-undo.
  def var dRequestResp as longchar      no-undo.
  def var dJson        as JsonObject    no-undo. /* used by outbound Json and the return inbound Json */

  define stream dOut1 .

  OUTPUT STREAM dOut1 TO "Test/output.txt" .

  dClient = ClientBuilder:Build():Client.
  dJson   = new JsonObject() .
  dJson:Add("name","morpheus11").
  dJson:Add("job","leader1221").

  dRequest  = RequestBuilder:Post(dURL,dJson)
                    :ContentType('application/json')
                    :AcceptJson()
                    :Request.
  dResponse = dClient:Execute(dRequest).

  if dResponse:StatusCode <> 200 then do:
    message subst("dResponse:StatusCode = &1", dResponse:StatusCode).
  end.
  else do:
    dJson = cast(dResponse:Entity, JsonObject).

    dJson = dJson:GetJsonObject ("json") .

//    dJson:Write(dRequestResp, true).

    BUFFER tt:read-json("JsonObject", dJson).
    for each tt on error undo, return error on stop undo, return error:

//BufferHelper:ShowBuffer(BUFFER tt:HANDLE).

      export stream dOut1 delimiter "|"
        tt.
    end.
    output stream dOut1 close.
  end.

and the output file:

"leader1221"|"morpheus11"