"-Begin-----------------------------------------------------------------

  Function Z_RFC_READ_TABLE_JSON.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(QUERY_TABLE) TYPE  DD02L-TABNAME
*"     VALUE(DELIMITER) TYPE  SONV-FLAG DEFAULT SPACE
*"     VALUE(NO_DATA) TYPE  SONV-FLAG DEFAULT SPACE
*"     VALUE(ROWSKIPS) TYPE  SOID-ACCNT DEFAULT 0
*"     VALUE(ROWCOUNT) TYPE  SOID-ACCNT DEFAULT 0
*"     VALUE(SORT) TYPE  CHAR1024 DEFAULT SPACE
*"  EXPORTING
*"     VALUE(DATA_JSON) TYPE  SDBLIN1024_TAB
*"  TABLES
*"      OPTIONS STRUCTURE  ZRFC_DB_OPT
*"      FIELDS STRUCTURE  RFC_DB_FLD
*"      DATA STRUCTURE  ZTAB8192
*"  EXCEPTIONS
*"      TABLE_NOT_AVAILABLE
*"      TABLE_WITHOUT_DATA
*"      OPTION_NOT_VALID
*"      FIELD_NOT_VALID
*"      DATA_BUFFER_EXCEEDED
*"----------------------------------------------------------------------

"Create a structure called ZRFC_DB_OPT with the component TEXT and the
"component type CHAR1024.
"Create a domain called ZSYSCHAR8192 with the data type CHAR and the
"length 8192.
"Create a structure called ZTAB8192 with the component WA and the new
"component type ZSYSCHAR8192. In this data type add the domain
"ZSYSCHAR8192.

* ----------------------------------------------------------------------
*  find out about the structure of QUERY_TABLE
* ----------------------------------------------------------------------
DATA BEGIN OF TABLE_STRUCTURE OCCURS 10.
        INCLUDE STRUCTURE DFIES.
DATA END OF TABLE_STRUCTURE.

DATA:
  TABLE_TYPE TYPE DD02V-TABCLASS,
  strJSON Type SDBLIN1024,
  cntData Type i,
  cntLine Type i,
  Len Type i,
  LastChar(1) Type c
  .

CALL FUNCTION 'DDIF_FIELDINFO_GET'
  EXPORTING
    TABNAME              = QUERY_TABLE
*   FIELDNAME            = ' '
*   LANGU                = SY-LANGU
*   LFIELDNAME           = ' '
*   ALL_TYPES            = ' '
*   GROUP_NAMES          = ' '
  IMPORTING
*   X030L_WA             =
    DDOBJTYPE            = TABLE_TYPE
*   DFIES_WA             =
*   LINES_DESCR          =
  TABLES
    DFIES_TAB            = TABLE_STRUCTURE
*   FIXED_VALUES         =
  EXCEPTIONS
    NOT_FOUND            = 1
    INTERNAL_ERROR       = 2
    OTHERS               = 3
          .
IF SY-SUBRC <> 0.
  RAISE TABLE_NOT_AVAILABLE.
ENDIF.
IF TABLE_TYPE = 'INTTAB'.
  RAISE TABLE_WITHOUT_DATA.
ENDIF.

* ----------------------------------------------------------------------
*  isolate first field of DATA as output field
*  (i.e. allow for changes to structure DATA!)
* ----------------------------------------------------------------------
DATA LINE_LENGTH TYPE I.
FIELD-SYMBOLS <D>.
ASSIGN COMPONENT 0 OF STRUCTURE DATA TO <D>.
DESCRIBE FIELD <D> LENGTH LINE_LENGTH in character mode.

* ----------------------------------------------------------------------
*  if FIELDS are not specified, read all available fields
* ----------------------------------------------------------------------
DATA NUMBER_OF_FIELDS TYPE I.
DESCRIBE TABLE FIELDS LINES NUMBER_OF_FIELDS.

IF NUMBER_OF_FIELDS = 0.
  LOOP AT TABLE_STRUCTURE.
    MOVE TABLE_STRUCTURE-FIELDNAME TO FIELDS-FIELDNAME.
    APPEND FIELDS.
  ENDLOOP.
ENDIF.

* ----------------------------------------------------------------------
*  for each field which has to be read, copy structure information
*  into tables FIELDS_INT (internal use) and FIELDS (output)
* ----------------------------------------------------------------------
DATA: BEGIN OF FIELDS_INT OCCURS 10,
        FIELDNAME  LIKE TABLE_STRUCTURE-FIELDNAME,
        TYPE       LIKE TABLE_STRUCTURE-INTTYPE,
        DECIMALS   LIKE TABLE_STRUCTURE-DECIMALS,
        LENGTH_SRC LIKE TABLE_STRUCTURE-INTLEN,
        LENGTH_DST LIKE TABLE_STRUCTURE-LENG,
        OFFSET_SRC LIKE TABLE_STRUCTURE-OFFSET,
        OFFSET_DST LIKE TABLE_STRUCTURE-OFFSET,
      END OF FIELDS_INT,
      LINE_CURSOR TYPE I.

LINE_CURSOR = 0.
*  for each field which has to be read ...
LOOP AT FIELDS.

  READ TABLE TABLE_STRUCTURE WITH KEY FIELDNAME = FIELDS-FIELDNAME.
  IF SY-SUBRC NE 0.
    RAISE FIELD_NOT_VALID.
  ENDIF.

* compute the place for field contents in DATA rows:
* if not first field in row, allow space for delimiter
  IF LINE_CURSOR <> 0.
    IF NO_DATA EQ SPACE AND DELIMITER NE SPACE.
      MOVE DELIMITER TO DATA+LINE_CURSOR.
    ENDIF.
    LINE_CURSOR = LINE_CURSOR + STRLEN( DELIMITER ).
  ENDIF.

* ... copy structure information into tables FIELDS_INT
* (which is used internally during SELECT) ...
  FIELDS_INT-FIELDNAME  = TABLE_STRUCTURE-FIELDNAME.
  FIELDS_INT-LENGTH_SRC = TABLE_STRUCTURE-INTLEN.
  FIELDS_INT-LENGTH_DST = TABLE_STRUCTURE-LENG.
  FIELDS_INT-OFFSET_SRC = TABLE_STRUCTURE-OFFSET.
  FIELDS_INT-OFFSET_DST = LINE_CURSOR.
  FIELDS_INT-TYPE       = TABLE_STRUCTURE-INTTYPE.
  FIELDS_INT-DECIMALS   = TABLE_STRUCTURE-DECIMALS.
* compute the place for contents of next field in DATA rows
  LINE_CURSOR = LINE_CURSOR + TABLE_STRUCTURE-LENG.
  IF LINE_CURSOR > LINE_LENGTH AND NO_DATA EQ SPACE.
    RAISE DATA_BUFFER_EXCEEDED.
  ENDIF.
  APPEND FIELDS_INT.

* ... and into table FIELDS (which is output to the caller)
  FIELDS-FIELDTEXT = TABLE_STRUCTURE-FIELDTEXT.
  FIELDS-TYPE      = TABLE_STRUCTURE-INTTYPE.
  FIELDS-LENGTH    = FIELDS_INT-LENGTH_DST.
  FIELDS-OFFSET    = FIELDS_INT-OFFSET_DST.
  MODIFY FIELDS.

ENDLOOP.
* end of loop at FIELDS

* ----------------------------------------------------------------------
*  read data from the database and copy relevant portions into DATA
* ----------------------------------------------------------------------
* output data only if NO_DATA equals space (otherwise the structure
* information in FIELDS is the only result of the module)

IF NO_DATA EQ SPACE.

  data: dref type ref to data.
  field-symbols: <wa> type any, <comp> type any.
  create data dref type (query_table).
  assign dref->* to <wa>.

  SELECT * FROM (QUERY_TABLE) INTO <WA> WHERE (OPTIONS) ORDER BY (SORT).

    IF SY-DBCNT GT ROWSKIPS.

*   copy all relevant fields into DATA (output) table
      LOOP AT FIELDS_INT.
        IF FIELDS_INT-TYPE = 'P'.
        ASSIGN COMPONENT FIELDS_INT-FIELDNAME
            OF STRUCTURE <WA> TO <COMP>
            TYPE     FIELDS_INT-TYPE
            DECIMALS FIELDS_INT-DECIMALS.
        ELSE.
        ASSIGN COMPONENT FIELDS_INT-FIELDNAME
            OF STRUCTURE <WA> TO <COMP>
            TYPE     FIELDS_INT-TYPE.
        ENDIF.
        MOVE <COMP> TO
            <D>+FIELDS_INT-OFFSET_DST(FIELDS_INT-LENGTH_DST).
      ENDLOOP.
*   end of loop at FIELDS_INT
      APPEND DATA.

      IF ROWCOUNT > 0 AND SY-DBCNT GE ROWCOUNT. EXIT. ENDIF.

    ENDIF.

  ENDSELECT.

  "-Export data in JSON format------------------------------------------
  "-
  "- Check the created JSON file with http://www.jsonlint.com validator
  "-
  "---------------------------------------------------------------------

    Describe Table DATA Lines cntData.

    strJSON = `{`.
    Append strJSON To DATA_JSON.
    Concatenate `  "` QUERY_TABLE '" : [' Into strJSON.
    Append strJSON To DATA_JSON.
    Loop At DATA.
      cntLine = cntLine + 1.

      strJSON = `    {`.
      Append strJSON To DATA_JSON.
      Loop At FIELDS.

        Move DATA-WA+FIELDS-OFFSET(FIELDS-LENGTH) To strJSON.
        Condense strJSON.
        Case FIELDS-TYPE.
          When 'I' Or 'b' Or 's' Or 'P' Or 'F'.
            Len = StrLen( strJSON ) - 1.
            Move strJSON+Len(1) To LastChar.
            If LastChar = '-'.
              Move strJSON+0(Len) To strJSON.
              Concatenate '-' strJSON Into strJSON.
            EndIf.
            Concatenate `      "` FIELDS-FIELDNAME `" : ` strJSON
              Into strJSON.
          When Others.
            Concatenate `      "` FIELDS-FIELDNAME `" : "` strJSON '"'
              Into strJSON.
        EndCase.
        If sy-tabix < sy-tfill.
          Concatenate strJSON ',' Into strJSON.
        EndIf.
        Append strJSON To DATA_JSON.

      EndLoop.
      strJSON = `    }`.
      If cntLine < cntData.
        Concatenate strJSON ',' Into strJSON.
      EndIf.
      Append strJSON To DATA_JSON.

    EndLoop.

    strJSON = `  ]`.
    Append strJSON To DATA_JSON.
    strJSON = `}`.
    Append strJSON To DATA_JSON.

ENDIF.

EndFunction.

"-End-------------------------------------------------------------------