ABAP to JSON

Converting an internal Table into a JSON string: ] ABAP2JSON [.

Here you find two methods that can be used as JSON Factory for any internal table.
You can provide a DDIC structure name for retrieving the fieldnames, or, when using a JOIN, VIEW or custom structure,
you may provide a field catalogue that will be merged into the JSON fields. Therefore it is also possible to extend a DDIC structure with custom fields for your JSON.

What can it be used for?

Well, it might be a very special use case.
But definitely you could use it in Business Server Pages when working with JAVASCRIPT libraries like YUI (YAHOO User Interface),
which expect JSON as datasources.

Known Issues

There might be a special issue handling QUAN and FLOAT Datatypes - well, since we are all creative minds, I am sure you will manage to handle this.

Anarchy

In no case we respect the naming conventions that are imposed by the company that build this programming language.

In fact we are able to recognize the good suggestions from those that stem from language deficencies and design flaws. 

Implementation of ABAP2JSON.

Makes use of two methods where the main one TABLE2JSON uses the second one ROW2JSON.

Use Type-Pool slis  for ALV Types.

METHOD ONE.

TABLE2JSON

 

 PARAMETERTYPE
REMARKS
 NAME STRING or C
 OPTIONAL, Name of the JSON ARRAY
 IT_DATA GENERIC TABLE your internal table recordset

IT_CUSTOM_FIELDS
 TABLE of lvc_s_fcat
 OPTIONAL, Custom fields to merge into the field catalogue
IV_STRUCTURE_NAME STRING or C
 OPTIONAL, Name of the DDIC Structure
 CV_JSON STRING RETURNING

 

 method TABLE2JSON .
type-pools slis.
FIELD-SYMBOLS: <LFS_DATA> TYPE ANY.

DATA: it_fieldcat type lvc_t_fcat,
      ls_custom_field type lvc_s_fcat,
      lv_tabname type DD02L-TABNAME .
DATA: iv_json_row type string.



IF IV_STRUCTURE_NAME IS SUPPLIED. "it's optional
*Fill intermediate data
lv_tabname = iv_structure_name.

*GET METADATA FROM DDIC
CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
 EXPORTING
    I_STRUCTURE_NAME             = lv_tabname
  CHANGING
    CT_FIELDCAT                  = it_fieldcat
 EXCEPTIONS
   INCONSISTENT_INTERFACE       = 1
   PROGRAM_ERROR                = 2
   OTHERS                       = 3
          .
IF SY-SUBRC <> 0.
  RETURN.
ENDIF.

ENDIF.

*Client wants custom fields - these are merged into the fieldcat
*This may apply for JOINS, VIEWS etc.
IF IT_CUSTOM_FIELDS IS SUPPLIED.
  APPEND LINES OF IT_CUSTOM_FIELDS TO it_fieldcat.
ENDIF.

IF NAME IS SUPPLIED.
  CONCATENATE '{"[' NAME" ': [' into CV_JSON .
ELSE.
  CV_JSON = '['.
ENDIF.


*iterate and get data for each field, appending the JSON output string.
LOOP AT IT_DATA ASSIGNING <LFS_DATA>.
  IV_JSON_ROW = ME->ROW2JSON( IT_FIELD_CAT = it_fieldcat IV_S_ROW = <LFS_DATA> ). "4.6
  CONCATENATE CV_JSON IV_JSON_ROW INTO CV_JSON SEPARATED BY SPACE.
  IF sy-tabix < lines( IT_DATA ).
    CONCATENATE CV_JSON ', ' INTO CV_JSON.
  ENDIF.

ENDLOOP.


CONCATENATE CV_JSON ']}' INTO CV_JSON SEPARATED BY SPACE.

endmethod.

Method Two.

ROW2JSON.

Processes each row of your data table. 

 

 PARAMETERTYPE
REMARKS
 IV_S_ROWANY
 A work area that holds the values of one table row.
 IT_FIELD_CATLVC_T_FCATThe field catalogue.
 CV_JSON STRING RETURNING
method ROW2JSON .
*  This code assumes Version 4.6/4.7 runtime (no regex available).
*  Assemble all Column-Names and Values into one JSON String.
  FIELD-SYMBOLS: <lfs_fc> TYPE lvc_s_fcat,
                 <lf_wa>   TYPE ANY,
                 <lf_comp_val> TYPE ANY.
 
  DATA: lv_current type string.
  CV_JSON = '{'.
  LOOP AT IT_FIELD_CAT ASSIGNING <lfs_fc>.
    ASSIGN iv_s_row TO <lf_wa>.
    ASSIGN COMPONENT <lfs_fc>-FIELDNAME OF STRUCTURE <lf_wa> TO <lf_comp_val>.
    IF <lf_comp_val> IS NOT ASSIGNED.
      CV_JSON = SPACE.
      RETURN.
    ENDIF.
    MOVE <lf_comp_val> TO lv_current.
*   Assemble
* TODO: check type of lf_comp_val to be only char-type
    CONCATENATE CV_JSON '"' <lfs_fc>-FIELDNAME '" : "' lv_current '"' INTO CV_JSON .
*   Comma only if not last element.
    IF sy-tabix < lines( IT_FIELD_CAT ).
      CONCATENATE CV_JSON ','  INTO CV_JSON SEPARATED by space.
    ENDIF.
  ENDLOOP.
  CONCATENATE CV_JSON '}' INTO CV_JSON SEPARATED BY SPACE.
endmethod.

 

Make a call.



CREATE OBJECT NET2112_DATA. "or whatsoever name you gave the class.

  SELECT  * from t100 UP TO 2 ROWS
   into table gt_table "of type T100 here
  where
     ARBGB = p_ARBGB
    AND MSGNR <> '000'
    AND SPRSL = SY-LANGU.

* Even we could just  have used the DDIC Name (T100), we use a custom fieldset with just one column for demonstration purposes. 
DATA: it_custom_fields type lvc_t_fcat,
      ls_field type lvc_s_fcat.

   ls_field-fieldname = 'TEXT'.
   append ls_field to it_custom_fields.
   ls_field-fieldname = 'MSGNR'.
   append ls_field to it_custom_fields.


  CALL METHOD NET2112_DATA->TABLE2JSON
    EXPORTING
      NAME                          =  'T100'
      IT_DATA                     =  gt_table
      IT_CUSTOM_FIELDS     =  it_custom_fields
     " IV_STRUCTURE_NAME = 'T100'
    RECEIVING
      CV_JSON           = lv_json
      .
write: / lv_json.

 

 And the output is:

 { "T100" :[{"TEXT" : "&1&2&3&4&5&6&7&8" ,"MSGNR" : "001" }, {"TEXT" : "Bitte gültigen Wert eingeben" ,"MSGNR" : "002" } ]}

 Use my (very rudimentary) JSON Validator to validate this string.

Have fun.

2112portals.com/Frank Kempf/OCT.2009

Letzte Aktualisierung ( Freitag, 2. April 2010 )