ajson, Automatic Update (#5237)

This commit is contained in:
github-actions[bot] 2021-12-27 17:37:29 +01:00 committed by GitHub
parent b2f62e91d5
commit 22a455e10c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 833 additions and 452 deletions

View File

@ -439,7 +439,7 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION.
CREATE OBJECT lo_to_abap.
TRY.
rv_value = lo_to_abap->to_timestamp( is_path = lr_item->* ).
rv_value = lo_to_abap->to_timestamp( lr_item->value ).
CATCH zcx_abapgit_ajson_error.
RETURN.
ENDTRY.
@ -801,13 +801,15 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION.
DATA lo_to_abap TYPE REF TO lcl_json_to_abap.
CLEAR ev_container.
lcl_json_to_abap=>bind(
CREATE OBJECT lo_to_abap
EXPORTING
ii_custom_mapping = mi_custom_mapping
ii_custom_mapping = mi_custom_mapping.
lo_to_abap->to_abap(
EXPORTING
it_nodes = zif_abapgit_ajson~mt_json_tree
CHANGING
c_obj = ev_container
co_instance = lo_to_abap ).
lo_to_abap->to_abap( mt_json_tree ).
c_container = ev_container ).
ENDMETHOD.
ENDCLASS.

View File

@ -548,206 +548,357 @@ ENDCLASS.
CLASS lcl_json_to_abap DEFINITION FINAL.
PUBLIC SECTION.
METHODS find_loc
METHODS constructor
IMPORTING
iv_path TYPE string
iv_name TYPE string OPTIONAL " not mandatory
iv_append_tables TYPE abap_bool DEFAULT abap_false
RETURNING
VALUE(r_ref) TYPE REF TO data
RAISING
zcx_abapgit_ajson_error.
CLASS-METHODS bind
IMPORTING
!ii_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL
CHANGING
c_obj TYPE any
co_instance TYPE REF TO lcl_json_to_abap.
!ii_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL.
METHODS to_abap
IMPORTING
it_nodes TYPE zif_abapgit_ajson=>ty_nodes_ts
it_nodes TYPE zif_abapgit_ajson=>ty_nodes_ts
CHANGING
c_container TYPE any
RAISING
zcx_abapgit_ajson_error.
METHODS to_timestamp
IMPORTING
is_path TYPE zif_abapgit_ajson=>ty_node
iv_value TYPE zif_abapgit_ajson=>ty_node-value
RETURNING
VALUE(rv_result) TYPE timestamp
RAISING
zcx_abapgit_ajson_error.
METHODS to_date
IMPORTING
iv_value TYPE zif_abapgit_ajson=>ty_node-value
RETURNING
VALUE(rv_result) TYPE d
RAISING
zcx_abapgit_ajson_error.
PRIVATE SECTION.
DATA mr_obj TYPE REF TO data.
TYPES:
BEGIN OF ty_type_cache,
type_path TYPE string,
target_field_name TYPE string,
dd TYPE REF TO cl_abap_datadescr,
type_kind LIKE cl_abap_typedescr=>typekind_any,
tab_item_buf TYPE REF TO data,
END OF ty_type_cache.
DATA mt_node_type_cache TYPE HASHED TABLE OF ty_type_cache WITH UNIQUE KEY type_path.
DATA mr_nodes TYPE REF TO zif_abapgit_ajson=>ty_nodes_ts.
DATA mi_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping.
METHODS any_to_abap
IMPORTING
iv_path TYPE string
is_parent_type TYPE ty_type_cache OPTIONAL
i_container_ref TYPE REF TO data
RAISING
zcx_abapgit_ajson_error.
METHODS value_to_abap
IMPORTING
is_node TYPE zif_abapgit_ajson=>ty_node
is_node_type TYPE ty_type_cache
i_container_ref TYPE REF TO data
RAISING
zcx_abapgit_ajson_error
cx_sy_conversion_no_number.
METHODS get_node_type
IMPORTING
is_node TYPE zif_abapgit_ajson=>ty_node OPTIONAL " Empty for root
is_parent_type TYPE ty_type_cache OPTIONAL
i_container_ref TYPE REF TO data OPTIONAL
RETURNING
VALUE(rs_node_type) TYPE ty_type_cache
RAISING
zcx_abapgit_ajson_error.
ENDCLASS.
CLASS lcl_json_to_abap IMPLEMENTATION.
METHOD bind.
CREATE OBJECT co_instance.
GET REFERENCE OF c_obj INTO co_instance->mr_obj.
co_instance->mi_custom_mapping = ii_custom_mapping.
METHOD constructor.
mi_custom_mapping = ii_custom_mapping.
ENDMETHOD.
METHOD to_abap.
DATA lr_ref TYPE REF TO data.
DATA lv_type TYPE c.
DATA lx TYPE REF TO cx_root.
FIELD-SYMBOLS <n> LIKE LINE OF it_nodes.
FIELD-SYMBOLS <value> TYPE any.
CLEAR c_container. " what about data/obj refs ?
CLEAR mt_node_type_cache.
GET REFERENCE OF c_container INTO lr_ref.
GET REFERENCE OF it_nodes INTO mr_nodes.
get_node_type( i_container_ref = lr_ref ). " Pre-cache root node type
any_to_abap(
iv_path = ''
i_container_ref = lr_ref ).
ENDMETHOD.
METHOD get_node_type.
DATA lv_node_type_path TYPE string.
DATA lo_sdescr TYPE REF TO cl_abap_structdescr.
DATA lo_tdescr TYPE REF TO cl_abap_tabledescr.
DATA lo_ddescr TYPE REF TO cl_abap_datadescr.
" Calculate type path
IF is_parent_type-type_kind = cl_abap_typedescr=>typekind_table.
lv_node_type_path = is_parent_type-type_path && '/-'. " table item type
ELSEIF is_parent_type-type_kind IS NOT INITIAL.
lv_node_type_path = is_parent_type-type_path && '/' && is_node-name.
ENDIF. " For root node lv_node_type_path remains ''
" Get or create cached
READ TABLE mt_node_type_cache INTO rs_node_type WITH KEY type_path = lv_node_type_path.
IF sy-subrc <> 0.
rs_node_type-type_path = lv_node_type_path.
IF mi_custom_mapping IS BOUND.
rs_node_type-target_field_name = to_upper( mi_custom_mapping->to_abap(
iv_path = is_node-path
iv_name = is_node-name ) ).
IF rs_node_type-target_field_name IS INITIAL.
rs_node_type-target_field_name = to_upper( is_node-name ).
ENDIF.
ELSE.
rs_node_type-target_field_name = to_upper( is_node-name ).
ENDIF.
CASE is_parent_type-type_kind.
WHEN 'h'. " Table
lo_tdescr ?= is_parent_type-dd.
rs_node_type-dd = lo_tdescr->get_table_line_type( ).
WHEN 'u' OR 'v'. " Structure
lo_sdescr ?= is_parent_type-dd.
lo_sdescr->get_component_type(
EXPORTING
p_name = rs_node_type-target_field_name
RECEIVING
p_descr_ref = rs_node_type-dd
EXCEPTIONS
component_not_found = 4 ).
IF sy-subrc <> 0.
zcx_abapgit_ajson_error=>raise( |Path not found| ).
ENDIF.
WHEN ''. " Root node
rs_node_type-dd ?= cl_abap_typedescr=>describe_by_data_ref( i_container_ref ).
WHEN OTHERS.
zcx_abapgit_ajson_error=>raise( |Unexpected parent type| ).
ENDCASE.
rs_node_type-type_kind = rs_node_type-dd->type_kind. " for caching and cleaner unintialized access
IF rs_node_type-type_kind = 'h'. " Table
lo_tdescr ?= rs_node_type-dd.
IF lo_tdescr->table_kind <> 'S'. " standard
lo_ddescr = lo_tdescr->get_table_line_type( ).
CREATE DATA rs_node_type-tab_item_buf TYPE HANDLE lo_ddescr.
ENDIF.
ENDIF.
INSERT rs_node_type INTO TABLE mt_node_type_cache.
ENDIF.
ENDMETHOD.
METHOD any_to_abap.
DATA ls_node_type LIKE LINE OF mt_node_type_cache.
DATA lx_ajson TYPE REF TO zcx_abapgit_ajson_error.
DATA lx_root TYPE REF TO cx_root.
DATA lr_target_field TYPE REF TO data.
FIELD-SYMBOLS <n> TYPE zif_abapgit_ajson=>ty_node.
FIELD-SYMBOLS <parent_stdtab> TYPE STANDARD TABLE.
FIELD-SYMBOLS <parent_anytab> TYPE ANY TABLE.
FIELD-SYMBOLS <parent_struc> TYPE any.
FIELD-SYMBOLS <tab_item> TYPE any.
" Assign container
CASE is_parent_type-type_kind.
WHEN 'h'. " Table
IF is_parent_type-tab_item_buf IS BOUND. " Indirect hint that table was sorted/hashed, see get_node_type.
ASSIGN i_container_ref->* TO <parent_anytab>.
ASSERT sy-subrc = 0.
lr_target_field = is_parent_type-tab_item_buf. " For hashed/sorted table - same buffer for all children
ASSIGN is_parent_type-tab_item_buf->* TO <tab_item>.
ASSERT sy-subrc = 0.
ELSE.
ASSIGN i_container_ref->* TO <parent_stdtab>.
ASSERT sy-subrc = 0.
ENDIF.
WHEN 'u' OR 'v'. " Structure
ASSIGN i_container_ref->* TO <parent_struc>.
ASSERT sy-subrc = 0.
ENDCASE.
TRY.
LOOP AT it_nodes ASSIGNING <n> USING KEY array_index.
lr_ref = find_loc(
iv_append_tables = abap_true
iv_path = <n>-path
iv_name = <n>-name ).
ASSIGN lr_ref->* TO <value>.
ASSERT sy-subrc = 0.
DESCRIBE FIELD <value> TYPE lv_type.
CASE <n>-type.
WHEN zif_abapgit_ajson=>node_type-null.
" Do nothing
WHEN zif_abapgit_ajson=>node_type-boolean.
<value> = boolc( <n>-value = 'true' ).
WHEN zif_abapgit_ajson=>node_type-number.
<value> = <n>-value.
WHEN zif_abapgit_ajson=>node_type-string.
IF lv_type = 'D' AND <n>-value IS NOT INITIAL.
DATA lv_y TYPE c LENGTH 4.
DATA lv_m TYPE c LENGTH 2.
DATA lv_d TYPE c LENGTH 2.
" array_index because stringified index goes in wrong order [1, 10, 2 ...]
LOOP AT mr_nodes->* ASSIGNING <n> USING KEY array_index WHERE path = iv_path.
FIND FIRST OCCURRENCE OF REGEX '^(\d{4})-(\d{2})-(\d{2})(T|$)'
IN <n>-value
SUBMATCHES lv_y lv_m lv_d.
IF sy-subrc <> 0.
zcx_abapgit_ajson_error=>raise(
iv_msg = 'Unexpected date format'
iv_location = <n>-path && <n>-name ).
ENDIF.
CONCATENATE lv_y lv_m lv_d INTO <value>.
ELSEIF lv_type = 'P' AND <n>-value IS NOT INITIAL.
<value> = to_timestamp( is_path = <n> ).
ELSE.
<value> = <n>-value.
" Get or create type cache record
IF is_parent_type-type_kind <> 'h' OR ls_node_type-type_kind IS INITIAL.
" table records are the same, no need to refetch twice
ls_node_type = get_node_type(
is_node = <n>
is_parent_type = is_parent_type ).
ENDIF.
" Validate node type
IF ls_node_type-type_kind CA 'lr'. " data/obj ref
" TODO maybe in future
zcx_abapgit_ajson_error=>raise( 'Cannot assign to ref' ).
ENDIF.
" Find target field reference
CASE is_parent_type-type_kind.
WHEN 'h'. " Table
IF NOT ls_node_type-target_field_name CO '0123456789'.
" Does not affect anything actually but for integrity
zcx_abapgit_ajson_error=>raise( 'Need index to access tables' ).
ENDIF.
WHEN zif_abapgit_ajson=>node_type-object.
IF NOT lv_type CO 'uv'.
zcx_abapgit_ajson_error=>raise(
iv_msg = 'Expected structure'
iv_location = <n>-path && <n>-name ).
ENDIF.
WHEN zif_abapgit_ajson=>node_type-array.
IF NOT lv_type CO 'h'.
zcx_abapgit_ajson_error=>raise(
iv_msg = 'Expected table'
iv_location = <n>-path && <n>-name ).
IF is_parent_type-tab_item_buf IS NOT BOUND. " Indirect hint that table was srt/hsh, see get_node_type
APPEND INITIAL LINE TO <parent_stdtab> REFERENCE INTO lr_target_field.
ASSERT sy-subrc = 0.
ENDIF.
WHEN 'u' OR 'v'.
FIELD-SYMBOLS <field> TYPE any.
ASSIGN COMPONENT ls_node_type-target_field_name OF STRUCTURE <parent_struc> TO <field>.
ASSERT sy-subrc = 0.
GET REFERENCE OF <field> INTO lr_target_field.
WHEN ''. " Root node
lr_target_field = i_container_ref.
WHEN OTHERS.
zcx_abapgit_ajson_error=>raise(
iv_msg = |Unexpected JSON type [{ <n>-type }]|
iv_location = <n>-path && <n>-name ).
zcx_abapgit_ajson_error=>raise( 'Unexpected parent type' ).
ENDCASE.
" Process value assignment
CASE <n>-type.
WHEN zif_abapgit_ajson=>node_type-object.
IF NOT ls_node_type-type_kind CO 'uv'.
zcx_abapgit_ajson_error=>raise( 'Expected structure' ).
ENDIF.
any_to_abap(
iv_path = <n>-path && <n>-name && '/'
is_parent_type = ls_node_type
i_container_ref = lr_target_field ).
WHEN zif_abapgit_ajson=>node_type-array.
IF NOT ls_node_type-type_kind = 'h'.
zcx_abapgit_ajson_error=>raise( 'Expected table' ).
ENDIF.
any_to_abap(
iv_path = <n>-path && <n>-name && '/'
is_parent_type = ls_node_type
i_container_ref = lr_target_field ).
WHEN OTHERS.
value_to_abap(
is_node = <n>
is_node_type = ls_node_type
i_container_ref = lr_target_field ).
ENDCASE.
IF is_parent_type-tab_item_buf IS BOUND. " Indirect hint that table was sorted/hashed, see get_node_type.
TRY.
INSERT <tab_item> INTO TABLE <parent_anytab>.
CATCH cx_sy_itab_duplicate_key.
sy-subrc = 4.
ENDTRY.
IF sy-subrc <> 0.
zcx_abapgit_ajson_error=>raise( 'Duplicate insertion' ).
ENDIF.
ENDIF.
ENDLOOP.
CATCH cx_sy_conversion_no_number INTO lx.
CATCH zcx_abapgit_ajson_error INTO lx_ajson.
IF lx_ajson->location IS INITIAL.
lx_ajson->set_location( <n>-path && <n>-name ).
ENDIF.
RAISE EXCEPTION lx_ajson.
CATCH cx_sy_conversion_no_number.
zcx_abapgit_ajson_error=>raise(
iv_msg = |Source is not a number|
iv_msg = 'Source is not a number'
iv_location = <n>-path && <n>-name ).
CATCH cx_root INTO lx_root.
zcx_abapgit_ajson_error=>raise(
iv_msg = lx_root->get_text( )
iv_location = <n>-path && <n>-name ).
ENDTRY.
ENDMETHOD.
METHOD find_loc.
METHOD value_to_abap.
DATA lt_path TYPE string_table.
DATA lv_trace TYPE string.
DATA lv_seg LIKE LINE OF lt_path.
DATA lv_type TYPE c.
DATA lv_size TYPE i.
DATA lv_index TYPE i.
FIELD-SYMBOLS <struc> TYPE any.
FIELD-SYMBOLS <table> TYPE STANDARD TABLE.
FIELD-SYMBOLS <value> TYPE any.
FIELD-SYMBOLS <seg> LIKE LINE OF lt_path.
FIELD-SYMBOLS <container> TYPE any.
SPLIT iv_path AT '/' INTO TABLE lt_path.
DELETE lt_path WHERE table_line IS INITIAL.
IF iv_name IS NOT INITIAL.
APPEND iv_name TO lt_path.
IF is_node_type-type_kind CA 'lruvh'. " refs, table, strucs
zcx_abapgit_ajson_error=>raise( |Unsupported target for value [{ is_node_type-type_kind }]| ).
ENDIF.
r_ref = mr_obj.
ASSIGN i_container_ref->* TO <container>.
ASSERT sy-subrc = 0.
LOOP AT lt_path ASSIGNING <seg>.
lv_trace = lv_trace && '/' && <seg>.
CASE is_node-type.
WHEN zif_abapgit_ajson=>node_type-null.
" Do nothing
WHEN zif_abapgit_ajson=>node_type-boolean.
" TODO: check type ?
<container> = boolc( is_node-value = 'true' ).
WHEN zif_abapgit_ajson=>node_type-number.
" TODO: check type ?
<container> = is_node-value.
IF mi_custom_mapping IS BOUND.
lv_seg = mi_custom_mapping->to_abap( iv_path = iv_path
iv_name = <seg> ).
ELSE.
CLEAR lv_seg.
ENDIF.
IF lv_seg IS INITIAL.
lv_seg = to_upper( <seg> ).
ELSE.
lv_seg = to_upper( lv_seg ).
ENDIF.
ASSIGN r_ref->* TO <struc>.
ASSERT sy-subrc = 0.
DESCRIBE FIELD <struc> TYPE lv_type.
IF lv_type CA 'lr'. " data/obj ref
" TODO maybe in future
zcx_abapgit_ajson_error=>raise(
iv_msg = 'Cannot assign to ref'
iv_location = lv_trace ).
ELSEIF lv_type = 'h'. " table
IF NOT lv_seg CO '0123456789'.
zcx_abapgit_ajson_error=>raise(
iv_msg = 'Need index to access tables'
iv_location = lv_trace ).
WHEN zif_abapgit_ajson=>node_type-string.
" TODO: check type ?
IF is_node_type-type_kind = 'D' AND is_node-value IS NOT INITIAL.
<container> = to_date( is_node-value ).
ELSEIF is_node_type-type_kind = 'P' AND is_node-value IS NOT INITIAL.
<container> = to_timestamp( is_node-value ).
ELSE.
<container> = is_node-value.
ENDIF.
lv_index = lv_seg.
ASSIGN r_ref->* TO <table>.
ASSERT sy-subrc = 0.
WHEN OTHERS.
zcx_abapgit_ajson_error=>raise( |Unexpected JSON type [{ is_node-type }]| ).
ENDCASE.
lv_size = lines( <table> ).
IF iv_append_tables = abap_true AND lv_index = lv_size + 1.
APPEND INITIAL LINE TO <table>.
ENDIF.
ENDMETHOD.
READ TABLE <table> INDEX lv_index ASSIGNING <value>.
IF sy-subrc <> 0.
zcx_abapgit_ajson_error=>raise(
iv_msg = 'Index not found in table'
iv_location = lv_trace ).
ENDIF.
METHOD to_date.
ELSEIF lv_type CA 'uv'. " structure
ASSIGN COMPONENT lv_seg OF STRUCTURE <struc> TO <value>.
IF sy-subrc <> 0.
zcx_abapgit_ajson_error=>raise(
iv_msg = 'Path not found'
iv_location = lv_trace ).
ENDIF.
ELSE.
zcx_abapgit_ajson_error=>raise(
iv_msg = 'Target is not deep'
iv_location = lv_trace ).
ENDIF.
GET REFERENCE OF <value> INTO r_ref.
ENDLOOP.
DATA lv_y TYPE c LENGTH 4.
DATA lv_m TYPE c LENGTH 2.
DATA lv_d TYPE c LENGTH 2.
FIND FIRST OCCURRENCE OF REGEX '^(\d{4})-(\d{2})-(\d{2})(T|$)'
IN iv_value
SUBMATCHES lv_y lv_m lv_d.
IF sy-subrc <> 0.
zcx_abapgit_ajson_error=>raise( 'Unexpected date format' ).
ENDIF.
CONCATENATE lv_y lv_m lv_d INTO rv_result.
ENDMETHOD.
@ -779,9 +930,10 @@ CLASS lcl_json_to_abap IMPLEMENTATION.
DATA lv_timestamp TYPE timestampl.
FIND FIRST OCCURRENCE OF REGEX lc_regex_ts_with_hour
IN is_path-value SUBMATCHES ls_timestamp-year ls_timestamp-month ls_timestamp-day ls_timestamp-t
ls_timestamp-hour ls_timestamp-minute ls_timestamp-second
ls_timestamp-local_sign ls_timestamp-local_hour ls_timestamp-local_minute.
IN iv_value SUBMATCHES
ls_timestamp-year ls_timestamp-month ls_timestamp-day ls_timestamp-t
ls_timestamp-hour ls_timestamp-minute ls_timestamp-second
ls_timestamp-local_sign ls_timestamp-local_hour ls_timestamp-local_minute.
IF sy-subrc = 0.
@ -790,13 +942,12 @@ CLASS lcl_json_to_abap IMPLEMENTATION.
ELSE.
FIND FIRST OCCURRENCE OF REGEX lc_regex_ts_utc
IN is_path-value SUBMATCHES ls_timestamp-year ls_timestamp-month ls_timestamp-day ls_timestamp-t
ls_timestamp-hour ls_timestamp-minute ls_timestamp-second.
IN iv_value SUBMATCHES
ls_timestamp-year ls_timestamp-month ls_timestamp-day ls_timestamp-t
ls_timestamp-hour ls_timestamp-minute ls_timestamp-second.
IF sy-subrc <> 0.
zcx_abapgit_ajson_error=>raise(
iv_msg = 'Unexpected timestamp format'
iv_location = is_path-path && is_path-name ).
zcx_abapgit_ajson_error=>raise( 'Unexpected timestamp format' ).
ENDIF.
ENDIF.
@ -810,21 +961,24 @@ CLASS lcl_json_to_abap IMPLEMENTATION.
CASE ls_timestamp-local_sign.
WHEN '-'.
lv_timestamp = cl_abap_tstmp=>add( tstmp = lv_timestamp
secs = lv_seconds_conv ).
lv_timestamp = cl_abap_tstmp=>add(
tstmp = lv_timestamp
secs = lv_seconds_conv ).
WHEN '+'.
lv_timestamp = cl_abap_tstmp=>subtractsecs( tstmp = lv_timestamp
secs = lv_seconds_conv ).
lv_timestamp = cl_abap_tstmp=>subtractsecs(
tstmp = lv_timestamp
secs = lv_seconds_conv ).
ENDCASE.
CATCH cx_parameter_invalid_range cx_parameter_invalid_type.
zcx_abapgit_ajson_error=>raise(
iv_msg = 'Unexpected error calculating timestamp'
iv_location = is_path-path && is_path-name ).
zcx_abapgit_ajson_error=>raise( 'Unexpected error calculating timestamp' ).
ENDTRY.
cl_abap_tstmp=>move( EXPORTING tstmp_src = lv_timestamp
IMPORTING tstmp_tgt = rv_result ).
cl_abap_tstmp=>move(
EXPORTING
tstmp_src = lv_timestamp
IMPORTING
tstmp_tgt = rv_result ).
ENDMETHOD.

View File

@ -1289,6 +1289,8 @@ CLASS ltcl_json_to_abap DEFINITION
b TYPE i,
END OF ty_struc,
tty_struc TYPE STANDARD TABLE OF ty_struc WITH DEFAULT KEY,
tty_struc_sorted TYPE SORTED TABLE OF ty_struc WITH UNIQUE KEY a,
tty_struc_hashed TYPE HASHED TABLE OF ty_struc WITH UNIQUE KEY a,
BEGIN OF ty_complex,
str TYPE string,
int TYPE i,
@ -1296,6 +1298,8 @@ CLASS ltcl_json_to_abap DEFINITION
bool TYPE abap_bool,
obj TYPE ty_struc,
tab TYPE tty_struc,
tab_plain TYPE string_table,
tab_hashed TYPE tty_struc_hashed,
oref TYPE REF TO object,
date1 TYPE d,
date2 TYPE d,
@ -1304,295 +1308,339 @@ CLASS ltcl_json_to_abap DEFINITION
timestamp3 TYPE timestamp,
END OF ty_complex.
METHODS find_loc FOR TESTING RAISING zcx_abapgit_ajson_error.
METHODS find_loc_negative FOR TESTING.
METHODS find_loc_append FOR TESTING RAISING zcx_abapgit_ajson_error.
METHODS to_abap FOR TESTING RAISING zcx_abapgit_ajson_error.
METHODS to_abap_negative FOR TESTING.
METHODS prepare_cut
EXPORTING
eo_cut TYPE REF TO lcl_json_to_abap
e_elem TYPE ty_struc
e_mock TYPE ty_complex.
METHODS to_abap_struc
FOR TESTING
RAISING zcx_abapgit_ajson_error.
METHODS to_abap_value
FOR TESTING
RAISING zcx_abapgit_ajson_error.
METHODS to_abap_array
FOR TESTING
RAISING zcx_abapgit_ajson_error.
METHODS to_abap_array_of_arrays
FOR TESTING
RAISING zcx_abapgit_ajson_error.
METHODS to_abap_w_tab_of_struc
FOR TESTING
RAISING zcx_abapgit_ajson_error.
METHODS to_abap_w_plain_tab
FOR TESTING
RAISING zcx_abapgit_ajson_error.
METHODS to_abap_hashed_tab
FOR TESTING
RAISING zcx_abapgit_ajson_error.
METHODS to_abap_sorted_tab
FOR TESTING
RAISING zcx_abapgit_ajson_error.
METHODS to_abap_hashed_plain_tab
FOR TESTING
RAISING zcx_abapgit_ajson_error.
METHODS to_abap_negative
FOR TESTING
RAISING zcx_abapgit_ajson_error.
ENDCLASS.
CLASS ltcl_json_to_abap IMPLEMENTATION.
METHOD prepare_cut.
e_mock-str = 'Hello'.
e_mock-int = 10.
e_mock-obj-a = 'World'.
e_elem-a = 'One'.
e_elem-b = 1.
APPEND e_elem TO e_mock-tab.
e_elem-a = 'two'.
e_elem-b = 2.
APPEND e_elem TO e_mock-tab.
lcl_json_to_abap=>bind(
CHANGING
c_obj = e_mock
co_instance = eo_cut ).
ENDMETHOD.
METHOD find_loc.
DATA last_elem TYPE ty_struc.
DATA ls_mock TYPE ty_complex.
DATA lo_cut TYPE REF TO lcl_json_to_abap.
prepare_cut(
IMPORTING
eo_cut = lo_cut
e_mock = ls_mock
e_elem = last_elem ).
DATA lr_ref TYPE REF TO data.
FIELD-SYMBOLS <val> TYPE any.
lr_ref = lo_cut->find_loc( 'str' ). " Relative also works but from root
ASSIGN lr_ref->* TO <val>.
cl_abap_unit_assert=>assert_equals(
act = <val>
exp = 'Hello' ).
lr_ref = lo_cut->find_loc( '/str' ).
ASSIGN lr_ref->* TO <val>.
cl_abap_unit_assert=>assert_equals(
act = <val>
exp = 'Hello' ).
lr_ref = lo_cut->find_loc( '/int' ).
ASSIGN lr_ref->* TO <val>.
cl_abap_unit_assert=>assert_equals(
act = <val>
exp = 10 ).
lr_ref = lo_cut->find_loc( '/obj/a' ).
ASSIGN lr_ref->* TO <val>.
cl_abap_unit_assert=>assert_equals(
act = <val>
exp = 'World' ).
lr_ref = lo_cut->find_loc( iv_path = '/obj'
iv_name = 'a' ).
ASSIGN lr_ref->* TO <val>.
cl_abap_unit_assert=>assert_equals(
act = <val>
exp = 'World' ).
lr_ref = lo_cut->find_loc( '/obj' ).
ASSIGN lr_ref->* TO <val>.
cl_abap_unit_assert=>assert_equals(
act = <val>
exp = ls_mock-obj ).
lr_ref = lo_cut->find_loc( '/' ).
ASSIGN lr_ref->* TO <val>.
cl_abap_unit_assert=>assert_equals(
act = <val>
exp = ls_mock ).
lr_ref = lo_cut->find_loc( '/tab/2' ).
ASSIGN lr_ref->* TO <val>.
cl_abap_unit_assert=>assert_equals(
act = <val>
exp = last_elem ).
lr_ref = lo_cut->find_loc( '/tab/1/a' ).
ASSIGN lr_ref->* TO <val>.
cl_abap_unit_assert=>assert_equals(
act = <val>
exp = 'One' ).
ENDMETHOD.
METHOD find_loc_append.
DATA last_elem TYPE ty_struc.
DATA ls_mock TYPE ty_complex.
DATA lo_cut TYPE REF TO lcl_json_to_abap.
DATA lx TYPE REF TO zcx_abapgit_ajson_error.
prepare_cut(
IMPORTING
eo_cut = lo_cut
e_mock = ls_mock
e_elem = last_elem ).
DATA lr_ref TYPE REF TO data.
FIELD-SYMBOLS <val> TYPE any.
lr_ref = lo_cut->find_loc( '/tab/1/a' ).
ASSIGN lr_ref->* TO <val>.
cl_abap_unit_assert=>assert_equals(
act = <val>
exp = 'One' ).
cl_abap_unit_assert=>assert_equals(
act = lines( ls_mock-tab )
exp = 2 ).
TRY.
lo_cut->find_loc( '/tab/3/a' ).
cl_abap_unit_assert=>fail( ).
CATCH zcx_abapgit_ajson_error INTO lx.
cl_abap_unit_assert=>assert_equals(
act = lx->message
exp = 'Index not found in table' ).
ENDTRY.
lr_ref = lo_cut->find_loc( iv_path = '/tab/3/a'
iv_append_tables = abap_true ).
ASSIGN lr_ref->* TO <val>.
cl_abap_unit_assert=>assert_equals(
act = <val>
exp = '' ).
cl_abap_unit_assert=>assert_equals(
act = lines( ls_mock-tab )
exp = 3 ).
TRY.
lo_cut->find_loc( '/tab/5/a' ).
cl_abap_unit_assert=>fail( ).
CATCH zcx_abapgit_ajson_error INTO lx.
cl_abap_unit_assert=>assert_equals(
act = lx->message
exp = 'Index not found in table' ).
ENDTRY.
ENDMETHOD.
METHOD find_loc_negative.
DATA lo_cut TYPE REF TO lcl_json_to_abap.
DATA lx TYPE REF TO zcx_abapgit_ajson_error.
DATA ls_mock TYPE ty_complex.
prepare_cut(
IMPORTING
e_mock = ls_mock " Must be here to keep reference alive
eo_cut = lo_cut ).
TRY.
lo_cut->find_loc( '/xyz' ).
cl_abap_unit_assert=>fail( ).
CATCH zcx_abapgit_ajson_error INTO lx.
cl_abap_unit_assert=>assert_equals(
act = lx->message
exp = 'Path not found' ).
ENDTRY.
TRY.
lo_cut->find_loc( '/oref/xyz' ).
cl_abap_unit_assert=>fail( ).
CATCH zcx_abapgit_ajson_error INTO lx.
cl_abap_unit_assert=>assert_equals(
act = lx->message
exp = 'Cannot assign to ref' ).
ENDTRY.
TRY.
lo_cut->find_loc( '/tab/xyz' ).
cl_abap_unit_assert=>fail( ).
CATCH zcx_abapgit_ajson_error INTO lx.
cl_abap_unit_assert=>assert_equals(
act = lx->message
exp = 'Need index to access tables' ).
ENDTRY.
TRY.
lo_cut->find_loc( '/tab/5' ).
cl_abap_unit_assert=>fail( ).
CATCH zcx_abapgit_ajson_error INTO lx.
cl_abap_unit_assert=>assert_equals(
act = lx->message
exp = 'Index not found in table' ).
ENDTRY.
ENDMETHOD.
METHOD to_abap.
METHOD to_abap_struc.
DATA lo_cut TYPE REF TO lcl_json_to_abap.
DATA ls_mock TYPE ty_complex.
DATA ls_exp TYPE ty_complex.
DATA lv_exp_date TYPE d VALUE '20200728'.
DATA lv_exp_timestamp TYPE timestamp VALUE '20200728000000'.
lcl_json_to_abap=>bind(
CHANGING
c_obj = ls_mock
co_instance = lo_cut ).
DATA lo_nodes TYPE REF TO lcl_nodes_helper.
CREATE OBJECT lo_nodes.
lo_nodes->add( '/ | |object | | ' ).
lo_nodes->add( ' | |object | | ' ).
lo_nodes->add( '/ |str |str |hello | ' ).
lo_nodes->add( '/ |int |num |5 | ' ).
lo_nodes->add( '/ |float |num |5.5 | ' ).
lo_nodes->add( '/ |bool |bool |true | ' ).
lo_nodes->add( '/ |obj |object | | ' ).
lo_nodes->add( '/obj |a |str |world | ' ).
lo_nodes->add( '/obj/ |a |str |world | ' ).
lo_nodes->add( '/ |tab |array | | ' ).
lo_nodes->add( '/tab |1 |object | |1' ).
lo_nodes->add( '/tab/1 |a |str | One | ' ).
lo_nodes->add( '/tab |2 |object | |2' ).
lo_nodes->add( '/tab/2 |a |str | Two | ' ).
lo_nodes->add( '/ |date1 |str |2020-07-28 | ' ).
lo_nodes->add( '/ |date2 |str |2020-07-28T00:00:00Z | ' ).
lo_nodes->add( '/ |timestamp1 |str |2020-07-28T00:00:00 | ' ).
lo_nodes->add( '/ |timestamp2 |str |2020-07-28T00:00:00Z | ' ).
lo_nodes->add( '/ |timestamp3 |str |2020-07-28T01:00:00+01:00 | ' ).
lo_cut->to_abap( lo_nodes->sorted( ) ).
CREATE OBJECT lo_cut.
lo_cut->to_abap(
EXPORTING
it_nodes = lo_nodes->sorted( )
CHANGING
c_container = ls_mock ).
ls_exp-str = 'hello'.
ls_exp-int = 5.
ls_exp-float = '5.5'.
ls_exp-bool = abap_true.
ls_exp-obj-a = 'world'.
ls_exp-date1 = lv_exp_date.
ls_exp-date2 = lv_exp_date.
ls_exp-timestamp1 = lv_exp_timestamp.
ls_exp-timestamp2 = lv_exp_timestamp.
ls_exp-timestamp3 = lv_exp_timestamp.
cl_abap_unit_assert=>assert_equals(
act = ls_mock-str
act = ls_mock
exp = ls_exp ).
ENDMETHOD.
METHOD to_abap_value.
DATA lo_cut TYPE REF TO lcl_json_to_abap.
DATA lv_mock TYPE string.
DATA lo_nodes TYPE REF TO lcl_nodes_helper.
CREATE OBJECT lo_nodes.
lo_nodes->add( ' | |str |hello | ' ).
CREATE OBJECT lo_cut.
lo_cut->to_abap(
EXPORTING
it_nodes = lo_nodes->sorted( )
CHANGING
c_container = lv_mock ).
cl_abap_unit_assert=>assert_equals(
act = lv_mock
exp = 'hello' ).
cl_abap_unit_assert=>assert_equals(
act = ls_mock-int
exp = 5 ).
cl_abap_unit_assert=>assert_equals(
act = ls_mock-float
exp = '5.5' ).
cl_abap_unit_assert=>assert_equals(
act = ls_mock-bool
exp = abap_true ).
cl_abap_unit_assert=>assert_equals(
act = ls_mock-obj-a
exp = 'world' ).
cl_abap_unit_assert=>assert_equals(
act = ls_mock-date1
exp = lv_exp_date ).
cl_abap_unit_assert=>assert_equals(
act = ls_mock-date2
exp = lv_exp_date ).
cl_abap_unit_assert=>assert_equals(
act = ls_mock-timestamp1
exp = lv_exp_timestamp ).
cl_abap_unit_assert=>assert_equals(
act = ls_mock-timestamp2
exp = lv_exp_timestamp ).
cl_abap_unit_assert=>assert_equals(
act = ls_mock-timestamp3
exp = lv_exp_timestamp ).
DATA ls_elem LIKE LINE OF ls_mock-tab.
cl_abap_unit_assert=>assert_equals(
act = lines( ls_mock-tab )
exp = 2 ).
ENDMETHOD.
METHOD to_abap_array.
DATA lo_cut TYPE REF TO lcl_json_to_abap.
DATA lt_mock TYPE string_table.
DATA lt_exp TYPE string_table.
DATA lo_nodes TYPE REF TO lcl_nodes_helper.
CREATE OBJECT lo_nodes.
lo_nodes->add( ' | |array | | ' ).
lo_nodes->add( '/ |1 |str |One |1' ).
lo_nodes->add( '/ |2 |str |Two |2' ).
CREATE OBJECT lo_cut.
lo_cut->to_abap(
EXPORTING
it_nodes = lo_nodes->sorted( )
CHANGING
c_container = lt_mock ).
APPEND 'One' TO lt_exp.
APPEND 'Two' TO lt_exp.
READ TABLE ls_mock-tab INTO ls_elem INDEX 1.
cl_abap_unit_assert=>assert_equals(
act = ls_elem-a
exp = 'One' ).
READ TABLE ls_mock-tab INTO ls_elem INDEX 2.
act = lt_mock
exp = lt_exp ).
ENDMETHOD.
METHOD to_abap_array_of_arrays.
DATA lo_cut TYPE REF TO lcl_json_to_abap.
DATA lt_mock TYPE TABLE OF string_table.
DATA lt_exp TYPE TABLE OF string_table.
DATA lt_tmp TYPE string_table.
DATA lo_nodes TYPE REF TO lcl_nodes_helper.
CREATE OBJECT lo_nodes.
lo_nodes->add( ' | |array | | ' ).
lo_nodes->add( '/ |1 |array | |1' ).
lo_nodes->add( '/ |2 |array | |2' ).
lo_nodes->add( '/1/ |1 |str |One |1' ).
lo_nodes->add( '/1/ |2 |str |Two |2' ).
lo_nodes->add( '/2/ |1 |str |Three |1' ).
lo_nodes->add( '/2/ |2 |str |Four |2' ).
CREATE OBJECT lo_cut.
lo_cut->to_abap(
EXPORTING
it_nodes = lo_nodes->sorted( )
CHANGING
c_container = lt_mock ).
APPEND 'One' TO lt_tmp.
APPEND 'Two' TO lt_tmp.
APPEND lt_tmp TO lt_exp.
CLEAR lt_tmp.
APPEND 'Three' TO lt_tmp.
APPEND 'Four' TO lt_tmp.
APPEND lt_tmp TO lt_exp.
cl_abap_unit_assert=>assert_equals(
act = ls_elem-a
exp = 'Two' ).
act = lt_mock
exp = lt_exp ).
ENDMETHOD.
METHOD to_abap_w_tab_of_struc.
DATA lo_cut TYPE REF TO lcl_json_to_abap.
DATA ls_mock TYPE ty_complex.
DATA ls_exp TYPE ty_complex.
DATA lo_nodes TYPE REF TO lcl_nodes_helper.
CREATE OBJECT lo_nodes.
lo_nodes->add( ' | |object | | ' ).
lo_nodes->add( '/ |tab |array | | ' ).
lo_nodes->add( '/tab/ |1 |object | |1' ).
lo_nodes->add( '/tab/1/|a |str |One | ' ).
lo_nodes->add( '/tab/ |2 |object | |2' ).
lo_nodes->add( '/tab/2/|a |str |Two | ' ).
CREATE OBJECT lo_cut.
lo_cut->to_abap(
EXPORTING
it_nodes = lo_nodes->sorted( )
CHANGING
c_container = ls_mock ).
DATA ls_elem LIKE LINE OF ls_exp-tab.
ls_elem-a = 'One'.
APPEND ls_elem TO ls_exp-tab.
ls_elem-a = 'Two'.
APPEND ls_elem TO ls_exp-tab.
cl_abap_unit_assert=>assert_equals(
act = ls_mock
exp = ls_exp ).
ENDMETHOD.
METHOD to_abap_w_plain_tab.
DATA lo_cut TYPE REF TO lcl_json_to_abap.
DATA ls_mock TYPE ty_complex.
DATA ls_exp TYPE ty_complex.
DATA lo_nodes TYPE REF TO lcl_nodes_helper.
CREATE OBJECT lo_nodes.
lo_nodes->add( ' | |object | | ' ).
lo_nodes->add( '/ |tab_plain |array | | ' ).
lo_nodes->add( '/tab_plain/ |1 |str |One |1' ).
lo_nodes->add( '/tab_plain/ |2 |str |Two |2' ).
CREATE OBJECT lo_cut.
lo_cut->to_abap(
EXPORTING
it_nodes = lo_nodes->sorted( )
CHANGING
c_container = ls_mock ).
APPEND 'One' TO ls_exp-tab_plain.
APPEND 'Two' TO ls_exp-tab_plain.
cl_abap_unit_assert=>assert_equals(
act = ls_mock
exp = ls_exp ).
ENDMETHOD.
METHOD to_abap_hashed_plain_tab.
DATA lo_cut TYPE REF TO lcl_json_to_abap.
DATA lt_mock TYPE HASHED TABLE OF string WITH UNIQUE KEY table_line.
DATA lt_exp TYPE HASHED TABLE OF string WITH UNIQUE KEY table_line.
DATA lo_nodes TYPE REF TO lcl_nodes_helper.
CREATE OBJECT lo_nodes.
lo_nodes->add( ' | |array | | ' ).
lo_nodes->add( '/ |1 |str |One |1' ).
lo_nodes->add( '/ |2 |str |Two |2' ).
CREATE OBJECT lo_cut.
lo_cut->to_abap(
EXPORTING
it_nodes = lo_nodes->sorted( )
CHANGING
c_container = lt_mock ).
INSERT `One` INTO TABLE lt_exp.
INSERT `Two` INTO TABLE lt_exp.
cl_abap_unit_assert=>assert_equals(
act = lt_mock
exp = lt_exp ).
ENDMETHOD.
METHOD to_abap_hashed_tab.
DATA lo_cut TYPE REF TO lcl_json_to_abap.
DATA lt_mock TYPE tty_struc_hashed.
DATA lt_exp TYPE tty_struc_hashed.
DATA lo_nodes TYPE REF TO lcl_nodes_helper.
CREATE OBJECT lo_nodes.
lo_nodes->add( ' | |array | | ' ).
lo_nodes->add( '/ |1 |object | |1' ).
lo_nodes->add( '/ |2 |object | |2' ).
lo_nodes->add( '/1/ |a |str |One | ' ).
lo_nodes->add( '/1/ |b |num |1 | ' ).
lo_nodes->add( '/2/ |a |str |Two | ' ).
lo_nodes->add( '/2/ |b |num |2 | ' ).
CREATE OBJECT lo_cut.
lo_cut->to_abap(
EXPORTING
it_nodes = lo_nodes->sorted( )
CHANGING
c_container = lt_mock ).
DATA ls_elem LIKE LINE OF lt_exp.
ls_elem-a = 'One'.
ls_elem-b = 1.
INSERT ls_elem INTO TABLE lt_exp.
ls_elem-a = 'Two'.
ls_elem-b = 2.
INSERT ls_elem INTO TABLE lt_exp.
cl_abap_unit_assert=>assert_equals(
act = lt_mock
exp = lt_exp ).
ENDMETHOD.
METHOD to_abap_sorted_tab.
DATA lo_cut TYPE REF TO lcl_json_to_abap.
DATA lt_mock TYPE tty_struc_sorted.
DATA lt_exp TYPE tty_struc_sorted.
DATA lo_nodes TYPE REF TO lcl_nodes_helper.
CREATE OBJECT lo_nodes.
lo_nodes->add( ' | |array | | ' ).
lo_nodes->add( '/ |1 |object | |1' ).
lo_nodes->add( '/ |2 |object | |2' ).
lo_nodes->add( '/1/ |a |str |One | ' ).
lo_nodes->add( '/1/ |b |num |1 | ' ).
lo_nodes->add( '/2/ |a |str |Two | ' ).
lo_nodes->add( '/2/ |b |num |2 | ' ).
CREATE OBJECT lo_cut.
lo_cut->to_abap(
EXPORTING
it_nodes = lo_nodes->sorted( )
CHANGING
c_container = lt_mock ).
DATA ls_elem LIKE LINE OF lt_exp.
ls_elem-a = 'One'.
ls_elem-b = 1.
INSERT ls_elem INTO TABLE lt_exp.
ls_elem-a = 'Two'.
ls_elem-b = 2.
INSERT ls_elem INTO TABLE lt_exp.
cl_abap_unit_assert=>assert_equals(
act = lt_mock
exp = lt_exp ).
ENDMETHOD.
@ -1601,19 +1649,21 @@ CLASS ltcl_json_to_abap IMPLEMENTATION.
DATA lo_cut TYPE REF TO lcl_json_to_abap.
DATA lx TYPE REF TO zcx_abapgit_ajson_error.
DATA ls_mock TYPE ty_complex.
lcl_json_to_abap=>bind(
CHANGING
c_obj = ls_mock
co_instance = lo_cut ).
CREATE OBJECT lo_cut.
DATA lo_nodes TYPE REF TO lcl_nodes_helper.
TRY.
CREATE OBJECT lo_nodes.
lo_nodes->add( '/ | |object | ' ).
lo_nodes->add( ' | |object | ' ).
lo_nodes->add( '/ |str |object | ' ).
lo_cut->to_abap( lo_nodes->sorted( ) ).
lo_cut->to_abap(
EXPORTING
it_nodes = lo_nodes->sorted( )
CHANGING
c_container = ls_mock ).
cl_abap_unit_assert=>fail( ).
CATCH zcx_abapgit_ajson_error INTO lx.
cl_abap_unit_assert=>assert_equals(
@ -1623,10 +1673,14 @@ CLASS ltcl_json_to_abap IMPLEMENTATION.
TRY.
CREATE OBJECT lo_nodes.
lo_nodes->add( '/ | |object | ' ).
lo_nodes->add( ' | |object | ' ).
lo_nodes->add( '/ |str |array | ' ).
lo_cut->to_abap( lo_nodes->sorted( ) ).
lo_cut->to_abap(
EXPORTING
it_nodes = lo_nodes->sorted( )
CHANGING
c_container = ls_mock ).
cl_abap_unit_assert=>fail( ).
CATCH zcx_abapgit_ajson_error INTO lx.
cl_abap_unit_assert=>assert_equals(
@ -1636,10 +1690,14 @@ CLASS ltcl_json_to_abap IMPLEMENTATION.
TRY.
CREATE OBJECT lo_nodes.
lo_nodes->add( '/ | |object | ' ).
lo_nodes->add( ' | |object | ' ).
lo_nodes->add( '/ |int |str |hello ' ).
lo_cut->to_abap( lo_nodes->sorted( ) ).
lo_cut->to_abap(
EXPORTING
it_nodes = lo_nodes->sorted( )
CHANGING
c_container = ls_mock ).
cl_abap_unit_assert=>fail( ).
CATCH zcx_abapgit_ajson_error INTO lx.
cl_abap_unit_assert=>assert_equals(
@ -1649,10 +1707,14 @@ CLASS ltcl_json_to_abap IMPLEMENTATION.
TRY.
CREATE OBJECT lo_nodes.
lo_nodes->add( '/ | |object | ' ).
lo_nodes->add( ' | |object | ' ).
lo_nodes->add( '/ |date1 |str |baddate ' ).
lo_cut->to_abap( lo_nodes->sorted( ) ).
lo_cut->to_abap(
EXPORTING
it_nodes = lo_nodes->sorted( )
CHANGING
c_container = ls_mock ).
cl_abap_unit_assert=>fail( ).
CATCH zcx_abapgit_ajson_error INTO lx.
cl_abap_unit_assert=>assert_equals(
@ -1660,6 +1722,94 @@ CLASS ltcl_json_to_abap IMPLEMENTATION.
exp = 'Unexpected date format' ).
ENDTRY.
TRY.
CREATE OBJECT lo_nodes.
lo_nodes->add( ' | |object | ' ).
lo_nodes->add( '/ |missing |str |123 ' ).
lo_cut->to_abap(
EXPORTING
it_nodes = lo_nodes->sorted( )
CHANGING
c_container = ls_mock ).
cl_abap_unit_assert=>fail( ).
CATCH zcx_abapgit_ajson_error INTO lx.
cl_abap_unit_assert=>assert_equals(
act = lx->message
exp = 'Path not found' ).
ENDTRY.
TRY.
DATA lt_str TYPE string_table.
CREATE OBJECT lo_nodes.
lo_nodes->add( ' | |array | | ' ).
lo_nodes->add( '/ |a |str |hello |1' ).
lo_cut->to_abap(
EXPORTING
it_nodes = lo_nodes->sorted( )
CHANGING
c_container = lt_str ).
cl_abap_unit_assert=>fail( ).
CATCH zcx_abapgit_ajson_error INTO lx.
cl_abap_unit_assert=>assert_equals(
act = lx->message
exp = 'Need index to access tables' ).
ENDTRY.
TRY.
DATA lr_obj TYPE REF TO object.
CREATE OBJECT lo_nodes.
lo_nodes->add( ' | |str |hello | ' ).
lo_cut->to_abap(
EXPORTING
it_nodes = lo_nodes->sorted( )
CHANGING
c_container = lr_obj ).
cl_abap_unit_assert=>fail( ).
CATCH zcx_abapgit_ajson_error INTO lx.
cl_abap_unit_assert=>assert_equals(
act = lx->message
exp = 'Cannot assign to ref' ).
ENDTRY.
TRY.
DATA lr_data TYPE REF TO data.
CREATE OBJECT lo_nodes.
lo_nodes->add( ' | |str |hello | ' ).
lo_cut->to_abap(
EXPORTING
it_nodes = lo_nodes->sorted( )
CHANGING
c_container = lr_data ).
cl_abap_unit_assert=>fail( ).
CATCH zcx_abapgit_ajson_error INTO lx.
cl_abap_unit_assert=>assert_equals(
act = lx->message
exp = 'Cannot assign to ref' ).
ENDTRY.
TRY.
DATA lt_hashed TYPE HASHED TABLE OF string WITH UNIQUE KEY table_line.
CREATE OBJECT lo_nodes.
lo_nodes->add( ' | |array | | ' ).
lo_nodes->add( '/ |1 |str |One |1' ).
lo_nodes->add( '/ |2 |str |One |2' ).
lo_cut->to_abap(
EXPORTING
it_nodes = lo_nodes->sorted( )
CHANGING
c_container = lt_hashed ).
cl_abap_unit_assert=>fail( ).
CATCH zcx_abapgit_ajson_error INTO lx.
cl_abap_unit_assert=>assert_equals(
act = lx->message
exp = 'Duplicate insertion' ).
ENDTRY.
ENDMETHOD.
ENDCLASS.

View File

@ -45,8 +45,18 @@ public section.
!IV_LOCATION type STRING optional
raising
zcx_abapgit_ajson_error .
methods set_location
importing
iv_location type string.
protected section.
private section.
types:
begin of ty_message_parts,
a1 like a1,
a2 like a1,
a3 like a1,
a4 like a1,
end of ty_message_parts.
ENDCLASS.
@ -77,21 +87,15 @@ endmethod.
method raise.
data:
begin of ls_msg,
a1 like a1,
a2 like a1,
a3 like a1,
a4 like a1,
end of ls_msg.
data ls_msg type ty_message_parts.
data lv_tmp type string.
if iv_location is initial.
ls_msg = iv_msg.
lv_tmp = iv_msg.
else.
data lv_tmp type string.
lv_tmp = iv_msg && | @{ iv_location }|.
ls_msg = lv_tmp.
endif.
ls_msg = lv_tmp.
raise exception type zcx_abapgit_ajson_error
exporting
@ -104,4 +108,25 @@ method raise.
a4 = ls_msg-a4.
endmethod.
method set_location.
data ls_msg type ty_message_parts.
data lv_tmp type string.
if iv_location is initial.
lv_tmp = message.
else.
lv_tmp = message && | @{ iv_location }|.
endif.
ls_msg = lv_tmp.
location = iv_location.
a1 = ls_msg-a1.
a2 = ls_msg-a2.
a3 = ls_msg-a3.
a4 = ls_msg-a4.
endmethod.
ENDCLASS.

View File

@ -8,6 +8,7 @@ class ltcl_error definition
methods raise for testing.
methods raise_w_location for testing.
methods set_location for testing.
endclass.
@ -49,4 +50,43 @@ class ltcl_error implementation.
endmethod.
method set_location.
data lx type ref to zcx_abapgit_ajson_error.
try.
zcx_abapgit_ajson_error=>raise( iv_msg = 'a'
iv_location = 'b' ).
cl_abap_unit_assert=>fail( ).
catch zcx_abapgit_ajson_error into lx.
cl_abap_unit_assert=>assert_equals(
exp = lx->location
act = 'b' ).
lx->set_location( 'c' ).
cl_abap_unit_assert=>assert_equals(
exp = lx->location
act = 'c' ).
cl_abap_unit_assert=>assert_equals(
exp = 'a @c'
act = lx->get_text( ) ).
endtry.
try.
zcx_abapgit_ajson_error=>raise( iv_msg = 'a' ).
cl_abap_unit_assert=>fail( ).
catch zcx_abapgit_ajson_error into lx.
cl_abap_unit_assert=>assert_equals(
exp = lx->location
act = '' ).
lx->set_location( 'c' ).
cl_abap_unit_assert=>assert_equals(
exp = lx->location
act = 'c' ).
cl_abap_unit_assert=>assert_equals(
exp = 'a @c'
act = lx->get_text( ) ).
endtry.
endmethod.
endclass.

View File

@ -1,7 +1,7 @@
INTERFACE zif_abapgit_ajson
PUBLIC.
CONSTANTS version TYPE string VALUE 'v1.1.1'. "#EC NOTEXT
CONSTANTS version TYPE string VALUE 'v1.1.2'. "#EC NOTEXT
CONSTANTS origin TYPE string VALUE 'https://github.com/sbcgua/ajson'. "#EC NOTEXT
CONSTANTS license TYPE string VALUE 'MIT'. "#EC NOTEXT

View File

@ -133,6 +133,15 @@
{"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_json_to_abap", "method": "find_loc", "note": "assert failed"},
{"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_json_to_abap", "method": "to_abap_negative"},
{"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_json_to_abap", "method": "to_abap_struc"},
{"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_json_to_abap", "method": "to_abap_hashed_plain_tab"},
{"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_json_to_abap", "method": "to_abap_sorted_tab"},
{"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_json_to_abap", "method": "to_abap_hashed_tab"},
{"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_json_to_abap", "method": "to_abap_w_plain_tab"},
{"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_json_to_abap", "method": "to_abap_w_tab_of_struc"},
{"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_json_to_abap", "method": "to_abap_array_of_arrays"},
{"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_json_to_abap", "method": "to_abap_value"},
{"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_json_to_abap", "method": "to_abap_array"},
{"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_json_to_abap", "method": "to_abap", "note": "Void type: TIMESTAMPL"},
{"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_obj"},
@ -163,6 +172,7 @@
{"object": "ZCL_ABAPGIT_AJSON_MAPPING", "class": "ltcl_camel_case", "method": "to_json_first_lower"},
{"object": "ZCL_ABAPGIT_AJSON_MAPPING", "class": "ltcl_fields", "method": "to_json"},
{"object": "ZCL_ABAPGIT_AJSON_MAPPING", "class": "ltcl_fields", "method": "to_abap"},
{"object": "ZCL_ABAPGIT_AJSON_MAPPING", "class": "ltcl_to_lower", "method": "to_json"},
{"object": "ZCL_ABAPGIT_AJSON_MAPPING", "class": "ltcl_to_upper", "method": "to_json"},