Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save mbtools/5ffe3f8c7e5f3862ec4a6d392da3cb61 to your computer and use it in GitHub Desktop.
Save mbtools/5ffe3f8c7e5f3862ec4a6d392da3cb61 to your computer and use it in GitHub Desktop.
Serialize/deserialize any table
CLASS zcl_settings_abapgit_ext_super DEFINITION
PUBLIC
INHERITING FROM zcl_abapgit_objects_super
CREATE PUBLIC.
************************************************************************
* Settings Extension for abapGit
*
* https://github.com/Marc-Bernard-Tools/ABAP-Settings-Ext-for-abapGit
*
* Copyright 2024 Marc Bernard <https://marcbernardtools.com/>
* SPDX-License-Identifier: MIT
************************************************************************
PUBLIC SECTION.
METHODS serialize_table_content
IMPORTING
iv_title TYPE string
iv_tabname TYPE tabname
iv_where TYPE string OPTIONAL
RAISING
zcx_abapgit_exception.
METHODS deserialize_table_content
IMPORTING
iv_title TYPE string
iv_tabname TYPE tabname
RAISING
zcx_abapgit_exception.
PROTECTED SECTION.
PRIVATE SECTION.
TYPES:
BEGIN OF ty_field,
fieldname TYPE fieldname,
inttype TYPE dd03l-inttype,
leng TYPE i,
decimals TYPE i,
END OF ty_field,
ty_fields TYPE STANDARD TABLE OF ty_field WITH KEY fieldname.
TYPES:
BEGIN OF ty_json,
tabname TYPE tabname,
where TYPE string,
data TYPE REF TO data,
fields TYPE ty_fields,
END OF ty_json.
METHODS _get_fields
IMPORTING
iv_tabname TYPE tabname
RETURNING
VALUE(rt_fields) TYPE ty_fields.
METHODS _convert_to_mustache
IMPORTING
ii_json TYPE REF TO zif_abapgit_ajson
it_fields TYPE ty_fields
RAISING
zcx_abapgit_ajson_error.
METHODS _convert_from_mustache
IMPORTING
ii_json TYPE REF TO zif_abapgit_ajson
RAISING
zcx_abapgit_ajson_error.
ENDCLASS.
CLASS zcl_settings_abapgit_ext_super IMPLEMENTATION.
METHOD deserialize_table_content.
DATA:
lv_data TYPE string,
ls_json TYPE ty_json,
li_json TYPE REF TO zif_abapgit_ajson,
lt_target TYPE ty_fields,
lr_data TYPE REF TO data,
lx_error TYPE REF TO zcx_abapgit_ajson_error.
FIELD-SYMBOLS:
<ls_data> TYPE any,
<lt_data> TYPE STANDARD TABLE.
lv_data = mo_files->read_string(
iv_extra = iv_title
iv_ext = 'json' ).
CREATE DATA lr_data TYPE STANDARD TABLE OF (iv_tabname).
ASSIGN lr_data->* TO <lt_data>.
ls_json-data = lr_data.
TRY.
li_json = zcl_abapgit_ajson=>parse( lv_data ).
_convert_from_mustache( li_json ).
li_json->to_abap( IMPORTING ev_container = ls_json ).
CATCH zcx_abapgit_ajson_error INTO lx_error.
zcx_abapgit_exception=>raise_with_text( lx_error ).
ENDTRY.
lt_target = _get_fields( iv_tabname ).
IF ls_json-fields <> lt_target.
BREAK-POINT. "might just be different field order
RETURN.
ENDIF.
ASSERT ls_json-tabname IS NOT INITIAL.
ASSERT <lt_data> IS NOT INITIAL.
IF ls_json-where IS INITIAL.
DELETE FROM (ls_json-tabname).
ELSE.
DELETE FROM (ls_json-tabname) WHERE (ls_json-where).
ENDIF.
INSERT (ls_json-tabname) FROM TABLE <lt_data>.
ENDMETHOD.
METHOD serialize_table_content.
DATA:
ls_json TYPE ty_json,
li_json TYPE REF TO zif_abapgit_ajson,
lr_data TYPE REF TO data,
lx_error TYPE REF TO zcx_abapgit_ajson_error.
FIELD-SYMBOLS <lt_data> TYPE ANY TABLE.
CREATE DATA lr_data TYPE TABLE OF (iv_tabname).
ASSIGN lr_data->* TO <lt_data>.
ls_json-tabname = iv_tabname.
ls_json-where = iv_where.
ls_json-data = lr_data.
ls_json-fields = _get_fields( iv_tabname ).
IF iv_where IS INITIAL.
SELECT * FROM (iv_tabname) INTO TABLE <lt_data> ORDER BY PRIMARY KEY.
ELSEIF iv_where CS 'MANDT'.
" lower releases:
" SELECT * FROM (iv_tabname) CLIENT SPECIFIED INTO TABLE <lt_data>
" WHERE (iv_where) ORDER BY PRIMARY KEY.
SELECT * FROM (iv_tabname) USING ALL CLIENTS
WHERE (iv_where) ORDER BY PRIMARY KEY
INTO TABLE @<lt_data>.
ELSE.
SELECT * FROM (iv_tabname) INTO TABLE <lt_data>
WHERE (iv_where) ORDER BY PRIMARY KEY.
ENDIF.
IF <lt_data> IS INITIAL.
RETURN.
ENDIF.
TRY.
li_json = zcl_abapgit_ajson=>new(
)->keep_item_order(
)->set( iv_path = '/' iv_val = ls_json
)->filter( lcl_ajson_filters=>create_empty_filter( ) ).
_convert_to_mustache(
ii_json = li_json
it_fields = ls_json-fields ).
mo_files->add_string(
iv_string = li_json->stringify( 2 )
iv_extra = iv_title
iv_ext = 'json' ).
CATCH zcx_abapgit_ajson_error INTO lx_error.
zcx_abapgit_exception=>raise_with_text( lx_error ).
ENDTRY.
ENDMETHOD.
METHOD _convert_from_mustache.
DATA:
lv_record TYPE string,
lv_fieldname TYPE string,
lv_original TYPE string,
lv_value TYPE string,
lv_timestamp TYPE timestamp,
lv_timestamps TYPE string,
lv_release TYPE c LENGTH 4.
lv_release = sy-saprl(1) && '.' && sy-saprl+1(2).
GET TIME STAMP FIELD lv_timestamp.
lv_timestamps = lv_timestamp.
LOOP AT ii_json->members( '/data' ) INTO lv_record.
LOOP AT ii_json->members( |/data/{ lv_record }| ) INTO lv_fieldname.
lv_original = ii_json->get( |/data/{ lv_record }/{ lv_fieldname }| ).
lv_value = lv_original.
REPLACE ALL OCCURRENCES OF '{{sid}}' IN lv_value WITH sy-sysid.
REPLACE ALL OCCURRENCES OF '{{user}}' IN lv_value WITH sy-uname.
REPLACE ALL OCCURRENCES OF '{{date}}' IN lv_value WITH sy-datum.
REPLACE ALL OCCURRENCES OF '{{time}}' IN lv_value WITH sy-uzeit.
REPLACE ALL OCCURRENCES OF '{{client}}' IN lv_value WITH sy-mandt.
REPLACE ALL OCCURRENCES OF '{{host}}' IN lv_value WITH sy-host.
REPLACE ALL OCCURRENCES OF '{{saprl}}' IN lv_value WITH sy-saprl.
REPLACE ALL OCCURRENCES OF '{{timestamp}}' IN lv_value WITH lv_timestamps.
REPLACE ALL OCCURRENCES OF '{{release}}' IN lv_value WITH lv_release.
IF lv_value <> lv_original.
ii_json->set( iv_path = |/data/{ lv_record }/{ lv_fieldname }| iv_val = lv_value ).
ENDIF.
ENDLOOP.
ENDLOOP.
ENDMETHOD.
METHOD _convert_to_mustache.
DATA:
lv_record TYPE string,
lv_fieldname TYPE string,
lv_original TYPE string,
lv_value TYPE string,
ls_field TYPE ty_field,
lv_release TYPE c LENGTH 4.
lv_release = sy-saprl(1) && '.' && sy-saprl+1(2).
LOOP AT ii_json->members( '/data' ) INTO lv_record.
LOOP AT ii_json->members( |/data/{ lv_record }| ) INTO lv_fieldname.
READ TABLE it_fields INTO ls_field WITH TABLE KEY fieldname = to_upper( lv_fieldname ).
ASSERT sy-subrc = 0.
lv_original = ii_json->get( |/data/{ lv_record }/{ lv_fieldname }| ).
lv_value = lv_original.
CASE ls_field-inttype.
WHEN 'C'.
IF ( lv_fieldname = 'mandt' OR lv_fieldname = 'client' ) AND lv_value = sy-mandt.
lv_value = '{{client}}'.
ELSEIF lv_value CS sy-sysid.
REPLACE ALL OCCURRENCES OF sy-sysid IN lv_value WITH '{{sid}}'.
ELSEIF lv_value CS sy-host.
REPLACE ALL OCCURRENCES OF sy-host IN lv_value WITH '{{host}}'.
ELSEIF lv_value = sy-saprl.
REPLACE ALL OCCURRENCES OF sy-saprl IN lv_value WITH '{{saprl}}'.
ELSEIF lv_value = lv_release.
REPLACE ALL OCCURRENCES OF lv_release IN lv_value WITH '{{release}}'.
ELSEIF lv_value = sy-uname.
lv_value = '{{user}}'.
ENDIF.
WHEN 'D'.
IF lv_value BETWEEN '20000101' AND sy-datum.
lv_value = '{{date}}'.
ENDIF.
WHEN 'T'.
lv_value = '{{time}}'.
WHEN 'P'.
IF ( ( ls_field-leng = 15 AND ls_field-decimals = 0 ) OR
( ls_field-leng = 21 AND ls_field-decimals = 7 ) ) AND
lv_value BETWEEN '20000101000000' AND '99991231000000'.
lv_value = '{{timestamp}}'.
ENDIF.
ENDCASE.
IF lv_value <> lv_original.
ii_json->set( iv_path = |/data/{ lv_record }/{ lv_fieldname }| iv_val = lv_value ).
ENDIF.
ENDLOOP.
ENDLOOP.
ENDMETHOD.
METHOD _get_fields.
DATA:
ls_field TYPE ty_field,
ls_dd03l TYPE dd03l,
lt_dd03l TYPE STANDARD TABLE OF dd03l WITH KEY tabname fieldname.
SELECT fieldname inttype leng decimals
FROM dd03l INTO CORRESPONDING FIELDS OF TABLE lt_dd03l
WHERE tabname = iv_tabname
AND as4local = 'A'
AND fieldname <> '.INCLUDE'
AND fieldname <> '.APPEND'
ORDER BY position.
LOOP AT lt_dd03l INTO ls_dd03l.
MOVE-CORRESPONDING ls_dd03l TO ls_field.
INSERT ls_field INTO TABLE rt_fields.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment