EPO Consulting Wiki - Strip JSON output for ABAP structures

Abap strip is a method to remove structure elements at runtime (creating a new structure via runtime). This is useful, when a webservice returns a potentially large structure, where each response uses only a fraction of the whole structure.

class /EPO1/CL_TOOLS, method ABAP_STRIP

This is a static method, and therefore can be called without creating an object of the class:

/epo1/cl_tools=>abap_strip(.. ).

Parameters

Meaning of the ABAP-STRIP - parameters:

  • IS_ANY: a structure to be stripped
  • IT_KEEP: list of elements, which should be kept (this list has the highest priority);
    format of the element names is like in ABAP: ELEMENT-SUB_ELEMENT-SUB_SUB_ELEMENT-..
  • IT_STRIP: list of elements, which should be stripped (except, when listed in IT_KEEP)
  • IV_STRIP_INITIAL: if 'X', remove all empty elements (structures, tables, primitive elements)
  • IV_RECURSIVE: if 'X', recurse to all substructures
  • IV_STRIP_EVERYTHING: if 'X', strip all elements - except when listed in IT_KEEP
  • EV_CHANGED: 'X', if the structure has been changed (else: ' ')
  • ER_ANY: reference to the new structure, filled with the values of the original structure

Note: elements and sub-elements are to be written as in ABAP (e.g. ELEMENT-SUB_ELEMENT-SUB_SUB_ELEMENT-...)

 

examples - how to use

structure, data

The following structure will be used for all examples below:

  TYPES:
    BEGIN OF lty_sub_struc,
      name  TYPE string,
      count TYPE i,
    END OF lty_sub_struc,

    BEGIN OF lty_struc,
      sub_1 TYPE lty_sub_struc,
      sub_2 TYPE lty_sub_struc,
      name  TYPE string,
      count TYPE i,
      char  TYPE char10,
      list  TYPE STANDARD TABLE OF string WITH NON-UNIQUE KEY table_line,
    END OF lty_struc.

The following data definition will be used for the examples below:

  FIELD-SYMBOLS:
    <stripped> TYPE any.

  DATA:
    ls_struc    TYPE        lty_struc,
    lr_stripped TYPE REF TO data,
    lt_keep     TYPE        /epo1/ec_string_table,
    lt_strip    TYPE        /epo1/ec_string_table.

 

accessing the stripped structure

Assign the referenced data to a field symbol:

  ASSIGN lr_stripped->* TO <stripped>.

Afterwards, the field symbol may be used like any other structure (e.g. to create a JSON string).

 

using IV_STRIP_INITIAL

Fill the structure only partially, every empty element (of the main structure) should be removed. This might be the most wanted use case:

  " fill the data
  ls_struc-sub_2-name  = 'substructure #2'.
  ls_struc-sub_2-count = 2.
  APPEND 'teststring' TO ls_struc-list.

Data of the structure:

ClipCapIt-200812-131629.PNG


So we would remove the whole SUB_1 structure (but not SUB_2) and the elements NAME, COUNT and CHAR (but not LIST).


Method call:

  /epo1/cl_tools=>abap_strip(
    EXPORTING
      IS_ANY                 = ls_struc
      IV_STRIP_INITIAL       = 'X'
    IMPORTING
      ER_ANY                 = lr_stripped ).

  ASSIGN lr_stripped->* TO <stripped>.

And the result (assigned to the field symbol '<STRIPPED>')

ClipCapIt-200807-170627.PNG

 

using IV_STRIP_INITIAL on an initial structure

SHOULD NEVER HAPPEN..

When creating a structure with the runtime, there must be at least one element. Whenever a structure is to be created, where there is no element left, we create a dummy element with the name '_'. This may also occur in sub-structures which must be kept, but all elements are to be stripped.

Data of the (empty) structure:

ClipCapIt-200812-131956.PNG

Method call:

  /epo1/cl_tools=>abap_strip(
    EXPORTING
      IS_ANY                 = ls_struc
      IV_STRIP_INITIAL       = 'X'
    IMPORTING
      ER_ANY                 = lr_stripped ).

  ASSIGN lr_stripped->* TO <stripped>.

So we would have to remove all of the structure elements, which is not possible. A dummy element is created:

ClipCapIt-200807-171316.PNG

 

using IT_KEEP with IV_STRIP_INITIAL

Elements, which are listed in IT_KEEP are handled with highest priority - they are never stripped. Use the ABAP - format to specify any element.

Fill the structure only partially, the main element COUNT should be kept, and the element COUNT of the structure SUB_1. Because the structure SUB_1 is listed in IT_KEEP, the elements of this structure are also evaluated for 'initial' - thus, the element SUB_1-NAME will be removed:

  " fill the data
  ls_struc-sub_2-name  = 'substructure #2'.
  APPEND 'teststring' TO ls_struc-list.

  " elements to keep
  APPEND 'COUNT'       TO lt_keep.
  APPEND 'SUB_1-COUNT' TO lt_keep.

Data of the structure:

ClipCapIt-200812-132845.PNG

Method call:

  /epo1/cl_tools=>abap_strip(
    EXPORTING
      IS_ANY                 = ls_struc
      IT_KEEP                = lt_keep
      IV_STRIP_INITIAL       = 'X'
    IMPORTING
      ER_ANY                 = lr_stripped ).

And the result (assigned to the field symbol '<STRIPPED>')

ClipCapIt-200812-140202.PNG

Result:

  • all empty elemens of the main structure has been removed
  • the empty element COUNT has survived
  • the empty element NAME of substructure SUB_1 has been removed
  • the empty element COUNT in the substructure SUB_1 has survived
  • the partly filled substructure SUB_2 has survived unchanged (even with the empty element COUNT)

 

using IT_KEEP with IV_STRIP_INITIAL and IV_RECURSIVE

The flag IV_RECURSIVE is only useful with IV_STRIP_INITIAL, as it causes the recursive removal of empty elements.

Fill the structure only partially, the main element COUNT should be kept, and the element COUNT of the structure SUB_1. Because of the flag IV_RECURSIVE, all substructures will be evaluated for empty elements.:

  " fill the data
  ls_struc-sub_2-name  = 'substructure #2'.
  APPEND 'teststring' TO ls_struc-list.

  " elements to keep
  APPEND 'COUNT'       TO lt_keep.
  APPEND 'SUB_1-COUNT' TO lt_keep.

Data of the structure:

ClipCapIt-200812-133655.PNG

So we would remove NAME, COUNT, CHAR and NAME of structure SUB_1.

Method call:

  /epo1/cl_tools=>abap_strip(
    EXPORTING
      IS_ANY                 = ls_struc
      IT_KEEP                = lt_keep
      IV_STRIP_INITIAL       = 'X'
      IV_RECURSIVE           = 'X'
    IMPORTING
      ER_ANY                 = lr_stripped ).

And the result (assigned to the field symbol '<STRIPPED>')

ClipCapIt-200812-134403.PNG

Result:

  • all empty elements of the main structure and substructures has been removed, except when listed in IT_KEEP
  • the empty element COUNT has survived
  • the empty element COUNT in the substructure SUB_1 has survived

 

using IT_STRIP

The table 'IT_STRIP' can be used to remove very special elements of a structure. This is independing, if that elements are empty or not.

This might be useful, when only a few elements should be removed.

  " fill the data
  ls_struc-sub_2-name  = 'substructure #2'.
  APPEND 'teststring' TO ls_struc-list.

  " elements to strip
  APPEND 'COUNT'       TO lt_strip.
  APPEND 'SUB_1-COUNT' TO lt_strip.
  APPEND 'SUB_2'       TO lt_strip.

Data of the structure:

ClipCapIt-200812-145716.PNG

We expect, that the listed elements are removed (even if not initial)

Method call:

/epo1/cl_tools=>abap_strip(
    EXPORTING
      IS_ANY                 = ls_struc
      IT_STRIP               = lt_strip
    IMPORTING
      ER_ANY                 = lr_stripped ).

Result:

ClipCapIt-200807-170117.PNG

The elements, listed in IT_STRIP, has been removed without touching the initial elements NAME, CHAR, etc.

 

using IV_STRIP_EVERYTHING together with IT_KEEP

The flag IV_STRIP_EVERYTHING is meant to really remove all elements. This is useful in combination with IT_KEEP, where few structure elements should be kept - and everything else removed.

Fill the data:

  " fill the data
  ls_struc-sub_2-name  = 'substructure #2'.
  ls_struc-sub_2-count = 2.
  APPEND 'teststring' TO ls_struc-list.

  " elements to keep
  APPEND 'SUB_2' TO lt_keep.
  APPEND 'COUNT' TO lt_keep.

Data of the structure:

ClipCapIt-200812-153236.PNG

..strip everything (red), which is not contained in IT_KEEP (green)

Method call:

  /epo1/cl_tools=>abap_strip(
    EXPORTING
      IS_ANY                 = ls_struc
      IT_KEEP                = it_keep
      IV_STRIP_EVERYTHING    = 'X'
    IMPORTING
      ER_ANY                 = lr_stripped )

And the result:

ClipCapIt-200812-153507.PNG

 

complete report sourcecode

Just to have a really complete coding (for simple copy/paste - and playing around) of the report 'Z_ABAP_STRIP'; the final breakpoint will invoke the debugger, where You can inspect the results:

 1 *&---------------------------------------------------------------------*
 2 *& Report Z_ABAP_STRIP
 3 *&---------------------------------------------------------------------*
 4 *&
 5 *&---------------------------------------------------------------------*
 6 REPORT Z_ABAP_STRIP.
 7 
 8   TYPES:
 9     BEGIN OF lty_sub_struc,
10       name  TYPE string,
11       count TYPE i,
12     END OF lty_sub_struc,
13 
14     BEGIN OF lty_struc,
15       sub_1 TYPE lty_sub_struc,
16       sub_2 TYPE lty_sub_struc,
17       name  TYPE string,
18       count TYPE i,
19       char  TYPE char10,
20       list  TYPE STANDARD TABLE OF string WITH NON-UNIQUE KEY table_line,
21     END OF lty_struc.
22 
23   FIELD-SYMBOLS:
24     <stripped> TYPE any.
25 
26   DATA:
27     ls_struc    TYPE        lty_struc,
28     lr_stripped TYPE REF TO data,
29     lt_keep     TYPE        /epo1/ec_string_table,
30     lt_strip    TYPE        /epo1/ec_string_table.
31 
32 
33   " fill the data
34 *  ls_struc-name        = 'TEST'.
35 *  ls_struc-count       = 5.
36 *  ls_struc-eins-name   = 'ONE'.
37 *  ls_struc-eins-count  = 1.
38 *  ls_struc-sub_2-name  = 'substructure #2'.
39 *  ls_struc-sub_2-count = 2.
40 *  APPEND 'teststring' TO ls_struc-list.
41 
42   " elements to keep
43 *  APPEND 'COUNT'       TO lt_keep.
44 *  APPEND 'SUB_1-COUNT' TO lt_keep.
45 *  APPEND 'SUB_2'       TO lt_keep.
46 *  APPEND 'COUNT'       TO lt_keep.
47 
48   " elements to strip
49 *  APPEND 'COUNT'       TO lt_strip.
50 *  APPEND 'SUB_1-COUNT' TO lt_strip.
51 *  APPEND 'SUB_2'       TO lt_strip.
52 
53   " get the stripped structure
54   /epo1/cl_tools=>abap_strip(
55     EXPORTING
56       IS_ANY                 = ls_struc
57       IT_KEEP                = lt_keep
58 *      IT_STRIP               = lt_strip
59 *      IV_STRIP_INITIAL       = 'X'
60 *      IV_STRIP_EVERYTHING    = 'X'
61 *      IV_RECURSIVE           = 'X'
62     IMPORTING
63       ER_ANY                 = lr_stripped ).
64 
65   ASSIGN lr_stripped->* TO <stripped>.

 

creating JSON strings

As an example, the stripped ABAP structure could be used to create a JSON string, using the static method /EPO1/CL_TOOLS=>ABAP_TO_JSON. For details, see our WIKI page JSON_API_in_SAP_ABAP.

Example: Stripping JSON Request for Outbound web service

In this example a JSON REST cloud service is called. Before the send call, the request json is stripped.

The class used for sending (CALL METHOD me->call_service) is /EPO1/CL_JSON_BASE_OUT.

 1   METHOD send.
 2     DATA ls_outgoinginvoice TYPE zcreateoutgoinginvoice.
 3     DATA ls_bapiret2 TYPE bapiret2.
 4     DATA lr_data TYPE REF TO data.
 5     FIELD-SYMBOLS <request> TYPE any.
 6 
 7     me->mv_service_id = 'SEND2CLOUD'.
 8     me->mv_service_operation = 'CreateOutgoingInvoice'.
 9 
10     CALL METHOD me->fill_outgoinginvoice_send
11       EXPORTING
12         is_invoice         = is_invoice
13         is_ubl21           = is_ubl21
14         is_ublcn21         = is_ublcn21
15         is_file_invoice    = is_file_invoice
16         is_file_attachment = is_file_attachment
17       IMPORTING
18         es_outgoinginvoice = ls_outgoinginvoice
19         es_bapiret2        = ls_bapiret2.
20 
21     IF ls_bapiret2 IS INITIAL.
22       CALL METHOD /epo1/cl_tools=>abap_strip
23         EXPORTING
24           is_any           = ls_outgoinginvoice
25 *         it_keep          =
26 *         it_strip         = lt_strip
27           iv_strip_initial = 'X'
28           iv_recursive     = 'X'
29 *         iv_strip_everything =
30         IMPORTING
31 *         ev_changed       =
32           er_any           = lr_data.
33 
34       ASSIGN lr_data->* TO <request>.
35 
36       CALL METHOD me->call_service
37         EXPORTING
38           is_outgoinginvoice = <request>
39         IMPORTING
40           es_bapiret2        = es_bapiret2.
41     ELSE.
42       es_bapiret2-id  = 'ZINV'.
43       es_bapiret2-number = '000'.
44       es_bapiret2-type    = 'E'.
45       es_bapiret2-message =  'error: No Invoice found'..
46       es_bapiret2-message_v1  = es_bapiret2-message.
47     ENDIF.
48 
49   ENDMETHOD.