Created
June 23, 2025 08:55
-
-
Save mbtools/5ffe3f8c7e5f3862ec4a6d392da3cb61 to your computer and use it in GitHub Desktop.
Serialize/deserialize any table
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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