From 95389c532bb01dac7ff67ad374ec4cdbd54e78cb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 14:47:44 +0100 Subject: [PATCH] ajson, Automatic Update (#5966) --- abaplint.json | 6 +- package.json | 8 +- src/json/zcl_abapgit_ajson.clas.abap | 208 +++++-- .../zcl_abapgit_ajson.clas.locals_imp.abap | 237 +++++++- .../zcl_abapgit_ajson.clas.testclasses.abap | 506 ++++++++++++++++++ src/json/zcl_abapgit_ajson_mapping.clas.abap | 78 ++- ...abapgit_ajson_mapping.clas.locals_def.abap | 51 +- ...abapgit_ajson_mapping.clas.locals_imp.abap | 162 +++++- ...bapgit_ajson_mapping.clas.testclasses.abap | 174 +++++- src/json/zcx_abapgit_ajson_error.clas.abap | 61 ++- ..._abapgit_ajson_error.clas.testclasses.abap | 21 + src/json/zif_abapgit_ajson.intf.abap | 29 + src/json/zif_abapgit_ajson_mapping.intf.abap | 23 +- .../aff/zcl_abapgit_json_handler.clas.abap | 4 +- test/abap_transpile.json | 1 + 15 files changed, 1460 insertions(+), 109 deletions(-) diff --git a/abaplint.json b/abaplint.json index 520597a60..362018aba 100644 --- a/abaplint.json +++ b/abaplint.json @@ -164,7 +164,9 @@ "cyclic_oo": false, "fully_type_constants": true, "keep_single_parameter_on_one_line": true, - "prefer_returning_to_exporting": true, + "prefer_returning_to_exporting": { + "exclude": ["/json/"] + }, "selection_screen_naming": true, "sicf_consistency": true, "sql_escape_host_variables": true, @@ -291,7 +293,7 @@ }, "line_length": { "length": 120, - "exclude": ["zcl_abapgit_object_pdts.clas.testclasses.abap"] + "exclude": ["zcl_abapgit_object_pdts.clas.testclasses.abap", "/json/"] }, "line_only_punc": { "ignoreExceptions": true diff --git a/package.json b/package.json index 762308640..b857ccdfe 100644 --- a/package.json +++ b/package.json @@ -26,12 +26,12 @@ ] }, "devDependencies": { - "@abaplint/cli": "^2.94.10", + "@abaplint/cli": "^2.94.13", "@abaplint/database-sqlite": "^2.3.93", - "@abaplint/runtime": "^2.3.93", - "@abaplint/transpiler-cli": "^2.3.93", + "@abaplint/runtime": "^2.3.94", + "@abaplint/transpiler-cli": "^2.3.94", "abapmerge": "^0.14.8", "c8": "^7.12.0", - "eslint": "^8.30.0" + "eslint": "^8.31.0" } } diff --git a/src/json/zcl_abapgit_ajson.clas.abap b/src/json/zcl_abapgit_ajson.clas.abap index c5727d04b..3fafc775d 100644 --- a/src/json/zcl_abapgit_ajson.clas.abap +++ b/src/json/zcl_abapgit_ajson.clas.abap @@ -1,6 +1,6 @@ CLASS zcl_abapgit_ajson DEFINITION PUBLIC - CREATE PRIVATE . + CREATE PUBLIC . PUBLIC SECTION. @@ -24,6 +24,7 @@ CLASS zcl_abapgit_ajson DEFINITION ALIASES: clear FOR zif_abapgit_ajson~clear, set FOR zif_abapgit_ajson~set, + setx FOR zif_abapgit_ajson~setx, set_boolean FOR zif_abapgit_ajson~set_boolean, set_string FOR zif_abapgit_ajson~set_string, set_integer FOR zif_abapgit_ajson~set_integer, @@ -35,6 +36,11 @@ CLASS zcl_abapgit_ajson DEFINITION push FOR zif_abapgit_ajson~push, stringify FOR zif_abapgit_ajson~stringify. + ALIASES: + clone FOR zif_abapgit_ajson~clone, + filter FOR zif_abapgit_ajson~filter, + map FOR zif_abapgit_ajson~map. + ALIASES: mt_json_tree FOR zif_abapgit_ajson~mt_json_tree, keep_item_order FOR zif_abapgit_ajson~keep_item_order, @@ -51,33 +57,44 @@ CLASS zcl_abapgit_ajson DEFINITION RAISING zcx_abapgit_ajson_error . - CLASS-METHODS create_empty + CLASS-METHODS create_empty " Might be deprecated, prefer using new( ) or create object IMPORTING !ii_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL + iv_keep_item_order TYPE abap_bool DEFAULT abap_false + iv_format_datetime TYPE abap_bool DEFAULT abap_true RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_ajson. " Experimental ! May change - CLASS-METHODS create_from + CLASS-METHODS create_from " TODO, rename to 'from' ? IMPORTING !ii_source_json TYPE REF TO zif_abapgit_ajson - !ii_filter TYPE REF TO zif_abapgit_ajson_filter OPTIONAL + !ii_filter TYPE REF TO zif_abapgit_ajson_filter OPTIONAL " Might be deprecated, use filter() instead + !ii_mapper TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL " Might be deprecated, use map() instead RETURNING VALUE(ro_instance) TYPE REF TO zcl_abapgit_ajson RAISING zcx_abapgit_ajson_error . - METHODS constructor. + METHODS constructor + IMPORTING + iv_keep_item_order TYPE abap_bool DEFAULT abap_false + iv_format_datetime TYPE abap_bool DEFAULT abap_true. + CLASS-METHODS new + IMPORTING + iv_keep_item_order TYPE abap_bool DEFAULT abap_false + iv_format_datetime TYPE abap_bool DEFAULT abap_true + RETURNING + VALUE(ro_instance) TYPE REF TO zcl_abapgit_ajson. PROTECTED SECTION. PRIVATE SECTION. - DATA mv_read_only TYPE abap_bool. - DATA mi_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping. - DATA mv_keep_item_order TYPE abap_bool. - DATA mv_format_datetime TYPE abap_bool. - " TODO restructure into zif_ajson=>ty_opts + CLASS-DATA go_float_regex TYPE REF TO cl_abap_regex. + + DATA ms_opts TYPE zif_abapgit_ajson=>ty_opts. + DATA mi_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping. " DEPRECATED, will be removed METHODS get_item IMPORTING @@ -107,44 +124,51 @@ ENDCLASS. CLASS zcl_abapgit_ajson IMPLEMENTATION. - METHOD zif_abapgit_ajson~opts. - rs_opts-read_only = mv_read_only. - rs_opts-format_datetime = mv_format_datetime. - rs_opts-keep_item_order = mv_keep_item_order. - ENDMETHOD. METHOD constructor. - format_datetime( abap_true ). + ms_opts-keep_item_order = iv_keep_item_order. + format_datetime( iv_format_datetime ). ENDMETHOD. METHOD create_empty. - CREATE OBJECT ro_instance. + CREATE OBJECT ro_instance + EXPORTING + iv_format_datetime = iv_format_datetime + iv_keep_item_order = iv_keep_item_order. ro_instance->mi_custom_mapping = ii_custom_mapping. ENDMETHOD. METHOD create_from. - DATA lo_filter_runner TYPE REF TO lcl_filter_runner. + DATA lo_mutator_queue TYPE REF TO lcl_mutator_queue. IF ii_source_json IS NOT BOUND. zcx_abapgit_ajson_error=>raise( 'Source not bound' ). ENDIF. - CREATE OBJECT ro_instance. + CREATE OBJECT ro_instance + EXPORTING + iv_format_datetime = ii_source_json->opts( )-format_datetime + iv_keep_item_order = ii_source_json->opts( )-keep_item_order. - IF ii_filter IS BOUND. - CREATE OBJECT lo_filter_runner. - lo_filter_runner->run( - EXPORTING - ii_filter = ii_filter - it_source_tree = ii_source_json->mt_json_tree - CHANGING - ct_dest_tree = ro_instance->mt_json_tree ). - ELSE. + IF ii_filter IS NOT BOUND AND ii_mapper IS NOT BOUND. ro_instance->mt_json_tree = ii_source_json->mt_json_tree. - " Copy keep order and custom mapping ??? + ELSE. + CREATE OBJECT lo_mutator_queue. + IF ii_mapper IS BOUND. + " Mapping goes first. But maybe it should be a freely definable queue of processors ? + lo_mutator_queue->add( lcl_mapper_runner=>new( ii_mapper ) ). + ENDIF. + IF ii_filter IS BOUND. + lo_mutator_queue->add( lcl_filter_runner=>new( ii_filter ) ). + ENDIF. + lo_mutator_queue->lif_mutator_runner~run( + EXPORTING + it_source_tree = ii_source_json->mt_json_tree + IMPORTING + et_dest_tree = ro_instance->mt_json_tree ). ENDIF. ENDMETHOD. @@ -201,6 +225,14 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION. ENDMETHOD. + METHOD new. + CREATE OBJECT ro_instance + EXPORTING + iv_format_datetime = iv_format_datetime + iv_keep_item_order = iv_keep_item_order. + ENDMETHOD. + + METHOD parse. DATA lo_parser TYPE REF TO lcl_json_parser. @@ -260,7 +292,7 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION. METHOD read_only_watchdog. - IF mv_read_only = abap_true. + IF ms_opts-read_only = abap_true. zcx_abapgit_ajson_error=>raise( 'This json instance is read only' ). ENDIF. ENDMETHOD. @@ -313,6 +345,11 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION. ENDMETHOD. + METHOD zif_abapgit_ajson~clone. + ri_json = create_from( me ). + ENDMETHOD. + + METHOD zif_abapgit_ajson~delete. read_only_watchdog( ). @@ -334,14 +371,21 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION. ENDMETHOD. + METHOD zif_abapgit_ajson~filter. + ri_json = create_from( + ii_source_json = me + ii_filter = ii_filter ). + ENDMETHOD. + + METHOD zif_abapgit_ajson~format_datetime. - mv_format_datetime = iv_use_iso. + ms_opts-format_datetime = iv_use_iso. ri_json = me. ENDMETHOD. METHOD zif_abapgit_ajson~freeze. - mv_read_only = abap_true. + ms_opts-read_only = abap_true. ENDMETHOD. @@ -462,11 +506,18 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION. METHOD zif_abapgit_ajson~keep_item_order. - mv_keep_item_order = abap_true. + ms_opts-keep_item_order = abap_true. ri_json = me. ENDMETHOD. + METHOD zif_abapgit_ajson~map. + ri_json = create_from( + ii_source_json = me + ii_mapper = ii_mapper ). + ENDMETHOD. + + METHOD zif_abapgit_ajson~members. DATA lv_normalized_path TYPE string. @@ -481,6 +532,11 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION. ENDMETHOD. + METHOD zif_abapgit_ajson~opts. + rs_opts = ms_opts. + ENDMETHOD. + + METHOD zif_abapgit_ajson~push. DATA lr_parent TYPE REF TO zif_abapgit_ajson=>ty_node. @@ -507,7 +563,7 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION. ls_new_path-name = |{ lv_new_index }|. lt_new_nodes = lcl_abap_to_json=>convert( - iv_keep_item_order = mv_keep_item_order + is_opts = ms_opts iv_data = iv_val is_prefix = ls_new_path ). READ TABLE lt_new_nodes INDEX 1 REFERENCE INTO lr_new_node. " assume first record is the array item - not ideal ! @@ -547,16 +603,14 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION. IF ls_split_path IS INITIAL. " Assign root, exceptional processing IF iv_node_type IS NOT INITIAL. mt_json_tree = lcl_abap_to_json=>insert_with_type( - iv_format_datetime = mv_format_datetime - iv_keep_item_order = mv_keep_item_order + is_opts = ms_opts iv_data = iv_val iv_type = iv_node_type is_prefix = ls_split_path ii_custom_mapping = mi_custom_mapping ). ELSE. mt_json_tree = lcl_abap_to_json=>convert( - iv_format_datetime = mv_format_datetime - iv_keep_item_order = mv_keep_item_order + is_opts = ms_opts iv_data = iv_val is_prefix = ls_split_path ii_custom_mapping = mi_custom_mapping ). @@ -586,8 +640,7 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION. IF iv_node_type IS NOT INITIAL. lt_new_nodes = lcl_abap_to_json=>insert_with_type( - iv_format_datetime = mv_format_datetime - iv_keep_item_order = mv_keep_item_order + is_opts = ms_opts iv_item_order = ls_deleted_node-order iv_data = iv_val iv_type = iv_node_type @@ -596,8 +649,7 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION. ii_custom_mapping = mi_custom_mapping ). ELSE. lt_new_nodes = lcl_abap_to_json=>convert( - iv_format_datetime = mv_format_datetime - iv_keep_item_order = mv_keep_item_order + is_opts = ms_opts iv_item_order = ls_deleted_node-order iv_data = iv_val iv_array_index = lv_array_index @@ -614,6 +666,74 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION. ENDMETHOD. + METHOD zif_abapgit_ajson~setx. + + DATA lv_path TYPE string. + DATA lv_val TYPE string. + DATA lv_int TYPE i. + DATA lv_dec TYPE decfloat34. + DATA lv_last TYPE i. + + IF iv_param IS INITIAL. + RETURN. + ENDIF. + + SPLIT iv_param AT ':' INTO lv_path lv_val. + CONDENSE lv_path. + CONDENSE lv_val. + + IF lv_val IS INITIAL. + RETURN. " Hmm ? or empty string ? or null ? + ENDIF. + + IF go_float_regex IS NOT BOUND. + CREATE OBJECT go_float_regex EXPORTING pattern = '^([1-9][0-9]*|0)\.[0-9]+$'. + " expects fractional, because ints are detected separately + ENDIF. + + IF lv_val = 'null'. + zif_abapgit_ajson~set_null( lv_path ). + ELSEIF lv_val = 'true'. + zif_abapgit_ajson~set_boolean( + iv_path = lv_path + iv_val = abap_true ). + ELSEIF lv_val = 'false'. + zif_abapgit_ajson~set_boolean( + iv_path = lv_path + iv_val = abap_false ). + ELSEIF lv_val CO '0123456789'. + lv_int = lv_val. + zif_abapgit_ajson~set_integer( + iv_path = lv_path + iv_val = lv_int ). + ELSEIF lv_val CO '0123456789.' AND go_float_regex->create_matcher( text = lv_val )->match( ) = abap_true. + lv_dec = lv_val. + zif_abapgit_ajson~set( + iv_path = lv_path + iv_val = lv_dec ). + ELSEIF lv_val+0(1) = '{' OR lv_val+0(1) = '['. + "Expect object/array, but no further checks, parser will catch errors + zif_abapgit_ajson~set( + iv_path = lv_path + iv_val = parse( lv_val ) ). + ELSE. " string + lv_last = strlen( lv_val ) - 1. + IF lv_val+0(1) = '"' AND lv_val+lv_last(1) = '"'. + lv_val = substring( + val = lv_val + off = 1 + len = lv_last - 1 ). + ENDIF. + zif_abapgit_ajson~set_string( + iv_path = lv_path + iv_val = lv_val ). + ENDIF. + + ri_json = me. + + ENDMETHOD. + + METHOD zif_abapgit_ajson~set_boolean. ri_json = me. @@ -733,7 +853,7 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION. rv_json = lcl_json_serializer=>stringify( it_json_tree = mt_json_tree - iv_keep_item_order = mv_keep_item_order + iv_keep_item_order = ms_opts-keep_item_order iv_indent = iv_indent ). ENDMETHOD. @@ -777,7 +897,7 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION. ls_new_node-name = ls_split_path-name. ls_new_node-type = zif_abapgit_ajson=>node_type-array. - IF mv_keep_item_order = abap_true AND ls_deleted_node IS NOT INITIAL. + IF ms_opts-keep_item_order = abap_true AND ls_deleted_node IS NOT INITIAL. ls_new_node-order = ls_deleted_node-order. ENDIF. diff --git a/src/json/zcl_abapgit_ajson.clas.locals_imp.abap b/src/json/zcl_abapgit_ajson.clas.locals_imp.abap index 769fb6ebd..af122e0f0 100644 --- a/src/json/zcl_abapgit_ajson.clas.locals_imp.abap +++ b/src/json/zcl_abapgit_ajson.clas.locals_imp.abap @@ -1073,8 +1073,7 @@ CLASS lcl_abap_to_json DEFINITION FINAL. is_prefix TYPE zif_abapgit_ajson=>ty_path_name OPTIONAL iv_array_index TYPE i DEFAULT 0 ii_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL - iv_keep_item_order TYPE abap_bool DEFAULT abap_false - iv_format_datetime TYPE abap_bool DEFAULT abap_false + is_opts TYPE zif_abapgit_ajson=>ty_opts OPTIONAL iv_item_order TYPE i DEFAULT 0 RETURNING VALUE(rt_nodes) TYPE zif_abapgit_ajson=>ty_nodes_tt @@ -1088,8 +1087,7 @@ CLASS lcl_abap_to_json DEFINITION FINAL. is_prefix TYPE zif_abapgit_ajson=>ty_path_name OPTIONAL iv_array_index TYPE i DEFAULT 0 ii_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL - iv_keep_item_order TYPE abap_bool DEFAULT abap_false - iv_format_datetime TYPE abap_bool DEFAULT abap_false + is_opts TYPE zif_abapgit_ajson=>ty_opts OPTIONAL iv_item_order TYPE i DEFAULT 0 RETURNING VALUE(rt_nodes) TYPE zif_abapgit_ajson=>ty_nodes_tt @@ -1226,8 +1224,8 @@ CLASS lcl_abap_to_json IMPLEMENTATION. CREATE OBJECT lo_converter. lo_converter->mi_custom_mapping = ii_custom_mapping. - lo_converter->mv_keep_item_order = iv_keep_item_order. - lo_converter->mv_format_datetime = iv_format_datetime. + lo_converter->mv_keep_item_order = is_opts-keep_item_order. + lo_converter->mv_format_datetime = is_opts-format_datetime. lo_converter->convert_any( EXPORTING @@ -1623,8 +1621,8 @@ CLASS lcl_abap_to_json IMPLEMENTATION. CREATE OBJECT lo_converter. lo_converter->mi_custom_mapping = ii_custom_mapping. - lo_converter->mv_keep_item_order = iv_keep_item_order. - lo_converter->mv_format_datetime = iv_format_datetime. + lo_converter->mv_keep_item_order = is_opts-keep_item_order. + lo_converter->mv_format_datetime = is_opts-format_datetime. lo_converter->insert_value_with_type( EXPORTING @@ -1689,20 +1687,35 @@ CLASS lcl_abap_to_json IMPLEMENTATION. ENDCLASS. +********************************************************************** +* MUTATOR INTERFACE +********************************************************************** + +INTERFACE lif_mutator_runner. + METHODS run + IMPORTING + it_source_tree TYPE zif_abapgit_ajson=>ty_nodes_ts + EXPORTING + et_dest_tree TYPE zif_abapgit_ajson=>ty_nodes_ts + RAISING + zcx_abapgit_ajson_error. +ENDINTERFACE. + ********************************************************************** * FILTER RUNNER ********************************************************************** CLASS lcl_filter_runner DEFINITION FINAL. PUBLIC SECTION. - METHODS run + INTERFACES lif_mutator_runner. + CLASS-METHODS new IMPORTING ii_filter TYPE REF TO zif_abapgit_ajson_filter - it_source_tree TYPE zif_abapgit_ajson=>ty_nodes_ts - CHANGING - ct_dest_tree TYPE zif_abapgit_ajson=>ty_nodes_ts - RAISING - zcx_abapgit_ajson_error. + RETURNING + VALUE(ro_instance) TYPE REF TO lcl_filter_runner. + METHODS constructor + IMPORTING + ii_filter TYPE REF TO zif_abapgit_ajson_filter. PRIVATE SECTION. DATA mi_filter TYPE REF TO zif_abapgit_ajson_filter. @@ -1721,14 +1734,20 @@ ENDCLASS. CLASS lcl_filter_runner IMPLEMENTATION. - METHOD run. + METHOD new. + CREATE OBJECT ro_instance EXPORTING ii_filter = ii_filter. + ENDMETHOD. + METHOD constructor. ASSERT ii_filter IS BOUND. mi_filter = ii_filter. - CLEAR ct_dest_tree. + ENDMETHOD. + METHOD lif_mutator_runner~run. + + CLEAR et_dest_tree. GET REFERENCE OF it_source_tree INTO mr_source_tree. - GET REFERENCE OF ct_dest_tree INTO mr_dest_tree. + GET REFERENCE OF et_dest_tree INTO mr_dest_tree. walk( iv_path = '' ). @@ -1788,3 +1807,187 @@ CLASS lcl_filter_runner IMPLEMENTATION. ENDMETHOD. ENDCLASS. + +********************************************************************** +* MAPPER RUNNER +********************************************************************** + +CLASS lcl_mapper_runner DEFINITION FINAL. + PUBLIC SECTION. + INTERFACES lif_mutator_runner. + CLASS-METHODS new + IMPORTING + ii_mapper TYPE REF TO zif_abapgit_ajson_mapping + RETURNING + VALUE(ro_instance) TYPE REF TO lcl_mapper_runner. + METHODS constructor + IMPORTING + ii_mapper TYPE REF TO zif_abapgit_ajson_mapping. + + PRIVATE SECTION. + DATA mi_mapper TYPE REF TO zif_abapgit_ajson_mapping. + DATA mr_source_tree TYPE REF TO zif_abapgit_ajson=>ty_nodes_ts. + DATA mr_dest_tree TYPE REF TO zif_abapgit_ajson=>ty_nodes_ts. + + METHODS process_deep_node + IMPORTING + iv_path TYPE string + iv_renamed_path TYPE string + iv_node_type TYPE zif_abapgit_ajson=>ty_node-type + RAISING + zcx_abapgit_ajson_error. + +ENDCLASS. + +CLASS lcl_mapper_runner IMPLEMENTATION. + + METHOD new. + CREATE OBJECT ro_instance EXPORTING ii_mapper = ii_mapper. + ENDMETHOD. + + METHOD constructor. + ASSERT ii_mapper IS BOUND. + mi_mapper = ii_mapper. + ENDMETHOD. + + METHOD lif_mutator_runner~run. + + FIELD-SYMBOLS LIKE LINE OF it_source_tree. + + READ TABLE it_source_tree WITH KEY path = `` name = `` ASSIGNING . + IF sy-subrc <> 0 OR NOT ( -type = zif_abapgit_ajson=>node_type-array OR -type = zif_abapgit_ajson=>node_type-object ). + " empty or one-value-only tree + et_dest_tree = it_source_tree. + RETURN. + ENDIF. + + CLEAR et_dest_tree. + GET REFERENCE OF it_source_tree INTO mr_source_tree. + GET REFERENCE OF et_dest_tree INTO mr_dest_tree. + INSERT INTO TABLE et_dest_tree. + + process_deep_node( + iv_path = `/` + iv_renamed_path = `/` + iv_node_type = -type ). + + ENDMETHOD. + + METHOD process_deep_node. + + + FIELD-SYMBOLS LIKE LINE OF mr_source_tree->*. + DATA ls_renamed_node LIKE . + + LOOP AT mr_source_tree->* ASSIGNING WHERE path = iv_path. + ls_renamed_node = . + IF iv_node_type <> zif_abapgit_ajson=>node_type-array. + " don't rename array item names -> they are numeric index + mi_mapper->rename_node( + EXPORTING + is_node = + CHANGING + cv_name = ls_renamed_node-name ). + IF ls_renamed_node-name IS INITIAL. + zcx_abapgit_ajson_error=>raise( + iv_msg = 'Renamed node name cannot be empty' + is_node = ). + ENDIF. + ENDIF. + ls_renamed_node-path = iv_renamed_path. + + INSERT ls_renamed_node INTO TABLE mr_dest_tree->*. + IF sy-subrc <> 0. " = 4 ? + zcx_abapgit_ajson_error=>raise( + iv_msg = 'Renamed node has a duplicate' + is_node = ls_renamed_node ). + ENDIF. + + " maybe also catch CX_SY_ITAB_DUPLICATE_KEY but secondary keys are not changed here, so not for now + + IF -type = zif_abapgit_ajson=>node_type-array OR -type = zif_abapgit_ajson=>node_type-object. + process_deep_node( + iv_path = iv_path && -name && `/` + iv_renamed_path = iv_renamed_path && ls_renamed_node-name && `/` + iv_node_type = -type ). + ENDIF. + + ENDLOOP. + + ENDMETHOD. + +ENDCLASS. + +********************************************************************** +* MUTATOR QUEUE +********************************************************************** + +CLASS lcl_mutator_queue DEFINITION FINAL. + PUBLIC SECTION. + INTERFACES lif_mutator_runner. + CLASS-METHODS new + RETURNING + VALUE(ro_instance) TYPE REF TO lcl_mutator_queue. + METHODS add + IMPORTING + ii_mutator TYPE REF TO lif_mutator_runner + RETURNING + VALUE(ro_self) TYPE REF TO lcl_mutator_queue. + + PRIVATE SECTION. + DATA mt_queue TYPE STANDARD TABLE OF REF TO lif_mutator_runner. + +ENDCLASS. + +CLASS lcl_mutator_queue IMPLEMENTATION. + + METHOD add. + IF ii_mutator IS BOUND. + APPEND ii_mutator TO mt_queue. + ENDIF. + ro_self = me. + ENDMETHOD. + + METHOD new. + CREATE OBJECT ro_instance. + ENDMETHOD. + + METHOD lif_mutator_runner~run. + + DATA li_mutator TYPE REF TO lif_mutator_runner. + DATA lv_qsize TYPE i. + FIELD-SYMBOLS LIKE it_source_tree. + FIELD-SYMBOLS LIKE it_source_tree. + DATA lr_buf TYPE REF TO zif_abapgit_ajson=>ty_nodes_ts. + + lv_qsize = lines( mt_queue ). + + IF lv_qsize = 0. + et_dest_tree = it_source_tree. + RETURN. + ENDIF. + + LOOP AT mt_queue INTO li_mutator. + IF sy-tabix = 1. + ASSIGN it_source_tree TO . + ELSE. + ASSIGN lr_buf->* TO . + ENDIF. + + IF sy-tabix = lv_qsize. + ASSIGN et_dest_tree TO . + ELSE. + CREATE DATA lr_buf. + ASSIGN lr_buf->* TO . + ENDIF. + + li_mutator->run( + EXPORTING + it_source_tree = + IMPORTING + et_dest_tree = ). + ENDLOOP. + + ENDMETHOD. + +ENDCLASS. diff --git a/src/json/zcl_abapgit_ajson.clas.testclasses.abap b/src/json/zcl_abapgit_ajson.clas.testclasses.abap index 77295aa2c..635349383 100644 --- a/src/json/zcl_abapgit_ajson.clas.testclasses.abap +++ b/src/json/zcl_abapgit_ajson.clas.testclasses.abap @@ -1976,6 +1976,9 @@ CLASS ltcl_writer_test DEFINITION FINAL METHODS set_with_type FOR TESTING RAISING zcx_abapgit_ajson_error. METHODS overwrite_w_keep_order_touch FOR TESTING RAISING zcx_abapgit_ajson_error. METHODS overwrite_w_keep_order_set FOR TESTING RAISING zcx_abapgit_ajson_error. + METHODS setx FOR TESTING RAISING zcx_abapgit_ajson_error. + METHODS setx_float FOR TESTING RAISING zcx_abapgit_ajson_error. + METHODS setx_complex FOR TESTING RAISING zcx_abapgit_ajson_error. METHODS set_with_type_slice IMPORTING @@ -3083,6 +3086,112 @@ CLASS ltcl_writer_test IMPLEMENTATION. ENDMETHOD. + METHOD setx. + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( '/a:1' )->stringify( ) + exp = '{"a":1}' ). + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( '/a : 1' )->stringify( ) + exp = '{"a":1}' ). + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( '/a:"1"' )->stringify( ) + exp = '{"a":"1"}' ). + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( '/a:abc' )->stringify( ) + exp = '{"a":"abc"}' ). + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( '/a:null' )->stringify( ) + exp = '{"a":null}' ). + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( '/a:true' )->stringify( ) + exp = '{"a":true}' ). + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( '/a:"true"' )->stringify( ) + exp = '{"a":"true"}' ). + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( '/a:false' )->stringify( ) + exp = '{"a":false}' ). + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( '/a/b:1' )->stringify( ) + exp = '{"a":{"b":1}}' ). + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( '/:1' )->stringify( ) + exp = '1' ). " Hmmm ? + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( ':1' )->stringify( ) + exp = '1' ). " Hmmm ? + + " TODO some negative tests like "/a:", "" + + ENDMETHOD. + + METHOD setx_float. + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( '/a:1.123' )->stringify( ) + exp = '{"a":1.123}' ). + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( '/a:00.123' )->stringify( ) + exp = '{"a":"00.123"}' ). " hmmm + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( '/a:.123' )->stringify( ) + exp = '{"a":".123"}' ). + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( '/a:123.' )->stringify( ) + exp = '{"a":"123."}' ). + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( '/a:1..123' )->stringify( ) + exp = '{"a":"1..123"}' ). + + ENDMETHOD. + + METHOD setx_complex. + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( '/a:{"b" : 1}' )->stringify( ) + exp = '{"a":{"b":1}}' ). + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( '/a:{}' )->stringify( ) + exp = '{"a":{}}' ). + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( '/a:[1, 2]' )->stringify( ) + exp = '{"a":[1,2]}' ). + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>new( )->setx( '/a:[]' )->stringify( ) + exp = '{"a":[]}' ). + + TRY. + zcl_abapgit_ajson=>new( )->setx( '/a:{"b" : 1' ). + cl_abap_unit_assert=>fail( ). + CATCH zcx_abapgit_ajson_error. + ENDTRY. + + TRY. + zcl_abapgit_ajson=>new( )->setx( '/a:[1, 2' ). + cl_abap_unit_assert=>fail( ). + CATCH zcx_abapgit_ajson_error. + ENDTRY. + + ENDMETHOD. + ENDCLASS. @@ -3999,3 +4108,400 @@ CLASS ltcl_filter_test IMPLEMENTATION. ENDMETHOD. ENDCLASS. + +********************************************************************** +* MAPPER TEST +********************************************************************** + +CLASS ltcl_mapper_test DEFINITION FINAL + FOR TESTING + DURATION SHORT + RISK LEVEL HARMLESS. + + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_mapping. + + PRIVATE SECTION. + + METHODS simple_test FOR TESTING RAISING zcx_abapgit_ajson_error. + METHODS array_test FOR TESTING RAISING zcx_abapgit_ajson_error. + METHODS duplication_test FOR TESTING RAISING zcx_abapgit_ajson_error. + METHODS empty_name_test FOR TESTING RAISING zcx_abapgit_ajson_error. + METHODS trivial FOR TESTING RAISING zcx_abapgit_ajson_error. + +ENDCLASS. + +CLASS ltcl_mapper_test IMPLEMENTATION. + + METHOD zif_abapgit_ajson_mapping~rename_node. + IF cv_name+0(1) = 'a'. + cv_name = to_upper( cv_name ). + ENDIF. + IF cv_name = 'set_this_empty'. + CLEAR cv_name. + ENDIF. + " watch dog for array + IF is_node-index <> 0. + cl_abap_unit_assert=>fail( 'rename must not be called for direct array items' ). + ENDIF. + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_abap. + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_json. + ENDMETHOD. + + METHOD simple_test. + + DATA lo_json TYPE REF TO zcl_abapgit_ajson. + DATA lo_json_filtered TYPE REF TO zcl_abapgit_ajson. + DATA lo_nodes_exp TYPE REF TO lcl_nodes_helper. + + lo_json = zcl_abapgit_ajson=>create_empty( ). + lo_json->set( + iv_path = '/ab' + iv_val = 1 ). + lo_json->set( + iv_path = '/bc' + iv_val = 2 ). + lo_json->set( + iv_path = '/c/ax' + iv_val = 3 ). + lo_json->set( + iv_path = '/c/by' + iv_val = 4 ). + lo_json->set( + iv_path = '/a/ax' + iv_val = 5 ). + lo_json->set( + iv_path = '/a/by' + iv_val = 6 ). + + lo_json_filtered = zcl_abapgit_ajson=>create_from( + ii_source_json = lo_json + ii_mapper = me ). + + CREATE OBJECT lo_nodes_exp. + lo_nodes_exp->add( ' | |object | | |4' ). + lo_nodes_exp->add( '/ |AB |num |1 | |0' ). + lo_nodes_exp->add( '/ |bc |num |2 | |0' ). + lo_nodes_exp->add( '/ |c |object | | |2' ). + lo_nodes_exp->add( '/c/ |AX |num |3 | |0' ). + lo_nodes_exp->add( '/c/ |by |num |4 | |0' ). + lo_nodes_exp->add( '/ |A |object | | |2' ). + lo_nodes_exp->add( '/A/ |AX |num |5 | |0' ). + lo_nodes_exp->add( '/A/ |by |num |6 | |0' ). + + cl_abap_unit_assert=>assert_equals( + act = lo_json_filtered->mt_json_tree + exp = lo_nodes_exp->sorted( ) ). + + ENDMETHOD. + + METHOD array_test. + + DATA lo_json TYPE REF TO zcl_abapgit_ajson. + DATA lo_json_filtered TYPE REF TO zcl_abapgit_ajson. + DATA lo_nodes_exp TYPE REF TO lcl_nodes_helper. + + lo_json = zcl_abapgit_ajson=>create_empty( ). + lo_json->touch_array( iv_path = '/' ). + lo_json->set( + iv_path = '/1/ab' + iv_val = 1 ). + lo_json->set( + iv_path = '/1/bc' + iv_val = 2 ). + lo_json->set( + iv_path = '/2/ax' + iv_val = 3 ). + lo_json->set( + iv_path = '/2/by' + iv_val = 4 ). + + lo_json_filtered = zcl_abapgit_ajson=>create_from( + ii_source_json = lo_json + ii_mapper = me ). + + CREATE OBJECT lo_nodes_exp. + lo_nodes_exp->add( ' | |array | | |2' ). + lo_nodes_exp->add( '/ |1 |object | |1|2' ). + lo_nodes_exp->add( '/ |2 |object | |2|2' ). + lo_nodes_exp->add( '/1/ |AB |num |1 | |0' ). + lo_nodes_exp->add( '/1/ |bc |num |2 | |0' ). + lo_nodes_exp->add( '/2/ |AX |num |3 | |0' ). + lo_nodes_exp->add( '/2/ |by |num |4 | |0' ). + + cl_abap_unit_assert=>assert_equals( + act = lo_json_filtered->mt_json_tree + exp = lo_nodes_exp->sorted( ) ). + ENDMETHOD. + + METHOD duplication_test. + + DATA lo_json TYPE REF TO zcl_abapgit_ajson. + DATA lx_err TYPE REF TO zcx_abapgit_ajson_error. + + lo_json = zcl_abapgit_ajson=>create_empty( ). + lo_json->set( + iv_path = '/ab' + iv_val = 1 ). + lo_json->set( + iv_path = '/AB' + iv_val = 2 ). + + TRY. + zcl_abapgit_ajson=>create_from( + ii_source_json = lo_json + ii_mapper = me ). + cl_abap_unit_assert=>fail( ). + CATCH zcx_abapgit_ajson_error INTO lx_err. + cl_abap_unit_assert=>assert_char_cp( + act = lx_err->get_text( ) + exp = 'Renamed node has a duplicate @/AB' ). + ENDTRY. + + ENDMETHOD. + + METHOD trivial. + + DATA lo_json TYPE REF TO zcl_abapgit_ajson. + DATA lo_json_filtered TYPE REF TO zcl_abapgit_ajson. + DATA lo_nodes_exp TYPE REF TO lcl_nodes_helper. + + lo_json = zcl_abapgit_ajson=>create_empty( ). + lo_json_filtered = zcl_abapgit_ajson=>create_from( + ii_source_json = lo_json + ii_mapper = me ). + cl_abap_unit_assert=>assert_initial( lo_json_filtered->mt_json_tree ). + + lo_json->set( + iv_path = '/' + iv_val = 1 ). + lo_json_filtered = zcl_abapgit_ajson=>create_from( + ii_source_json = lo_json + ii_mapper = me ). + + CREATE OBJECT lo_nodes_exp. + lo_nodes_exp->add( ' | |num |1 | |0' ). + cl_abap_unit_assert=>assert_equals( + act = lo_json_filtered->mt_json_tree + exp = lo_nodes_exp->sorted( ) ). + + ENDMETHOD. + + METHOD empty_name_test. + + DATA lo_json TYPE REF TO zcl_abapgit_ajson. + DATA lx_err TYPE REF TO zcx_abapgit_ajson_error. + + lo_json = zcl_abapgit_ajson=>create_empty( ). + lo_json->set( + iv_path = '/set_this_empty' + iv_val = 1 ). + + TRY. + zcl_abapgit_ajson=>create_from( + ii_source_json = lo_json + ii_mapper = me ). + cl_abap_unit_assert=>fail( ). + CATCH zcx_abapgit_ajson_error INTO lx_err. + cl_abap_unit_assert=>assert_char_cp( + act = lx_err->get_text( ) + exp = 'Renamed node name cannot be empty @/set_this_empty' ). + ENDTRY. + + ENDMETHOD. + +ENDCLASS. + +********************************************************************** +* CLONING TEST +********************************************************************** + +CLASS ltcl_cloning_test DEFINITION FINAL + FOR TESTING + DURATION SHORT + RISK LEVEL HARMLESS. + + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_mapping. + INTERFACES zif_abapgit_ajson_filter. + + PRIVATE SECTION. + + METHODS clone_test FOR TESTING RAISING zcx_abapgit_ajson_error. + METHODS filter_test FOR TESTING RAISING zcx_abapgit_ajson_error. + METHODS mapper_test FOR TESTING RAISING zcx_abapgit_ajson_error. + METHODS mapper_and_filter FOR TESTING RAISING zcx_abapgit_ajson_error. + METHODS opts_copying FOR TESTING RAISING zcx_abapgit_ajson_error. + +ENDCLASS. + +CLASS ltcl_cloning_test IMPLEMENTATION. + + METHOD clone_test. + + DATA li_json TYPE REF TO zif_abapgit_ajson. + DATA li_json_new TYPE REF TO zif_abapgit_ajson. + DATA lo_nodes_exp TYPE REF TO lcl_nodes_helper. + + li_json = zcl_abapgit_ajson=>create_empty( ). + li_json->set( + iv_path = '/ab' + iv_val = 1 ). + li_json->set( + iv_path = '/xy' + iv_val = 2 ). + + li_json_new = li_json->clone( ). + + CREATE OBJECT lo_nodes_exp. + lo_nodes_exp->add( ' | |object | | |2' ). + lo_nodes_exp->add( '/ |ab |num |1 | |0' ). + lo_nodes_exp->add( '/ |xy |num |2 | |0' ). + + cl_abap_unit_assert=>assert_equals( + act = li_json->mt_json_tree + exp = lo_nodes_exp->sorted( ) ). + cl_abap_unit_assert=>assert_equals( + act = li_json_new->mt_json_tree + exp = lo_nodes_exp->sorted( ) ). + + " ensure disconnection + li_json->set( + iv_path = '/ab' + iv_val = 5 ). + cl_abap_unit_assert=>assert_equals( + act = li_json->get_integer( '/ab' ) + exp = 5 ). + cl_abap_unit_assert=>assert_equals( + act = li_json_new->get_integer( '/ab' ) + exp = 1 ). + + ENDMETHOD. + + METHOD filter_test. + + DATA li_json TYPE REF TO zif_abapgit_ajson. + DATA li_json_new TYPE REF TO zif_abapgit_ajson. + DATA lo_nodes_exp TYPE REF TO lcl_nodes_helper. + + li_json = zcl_abapgit_ajson=>create_empty( ). + li_json->set( + iv_path = '/ab' + iv_val = 1 ). + li_json->set( + iv_path = '/xy' + iv_val = 2 ). + + li_json_new = li_json->filter( me ). + + CREATE OBJECT lo_nodes_exp. + lo_nodes_exp->add( ' | |object | | |1' ). + lo_nodes_exp->add( '/ |ab |num |1 | |0' ). + + cl_abap_unit_assert=>assert_equals( + act = li_json_new->mt_json_tree + exp = lo_nodes_exp->sorted( ) ). + + ENDMETHOD. + + METHOD mapper_test. + + DATA li_json TYPE REF TO zif_abapgit_ajson. + DATA li_json_new TYPE REF TO zif_abapgit_ajson. + DATA lo_nodes_exp TYPE REF TO lcl_nodes_helper. + + li_json = zcl_abapgit_ajson=>create_empty( ). + li_json->set( + iv_path = '/ab' + iv_val = 1 ). + li_json->set( + iv_path = '/xy' + iv_val = 2 ). + + li_json_new = li_json->map( me ). + + CREATE OBJECT lo_nodes_exp. + lo_nodes_exp->add( ' | |object | | |2' ). + lo_nodes_exp->add( '/ |AB |num |1 | |0' ). + lo_nodes_exp->add( '/ |xy |num |2 | |0' ). + + cl_abap_unit_assert=>assert_equals( + act = li_json_new->mt_json_tree + exp = lo_nodes_exp->sorted( ) ). + + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~rename_node. + IF cv_name+0(1) = 'a'. + cv_name = to_upper( cv_name ). + ENDIF. + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_abap. + + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_json. + + ENDMETHOD. + + METHOD zif_abapgit_ajson_filter~keep_node. + rv_keep = boolc( is_node-name IS INITIAL OR is_node-name+0(1) <> 'x' ). + ENDMETHOD. + + METHOD mapper_and_filter. + + DATA li_json TYPE REF TO zif_abapgit_ajson. + DATA li_json_new TYPE REF TO zif_abapgit_ajson. + DATA lo_nodes_exp TYPE REF TO lcl_nodes_helper. + + li_json = zcl_abapgit_ajson=>new( ). + li_json->set( + iv_path = '/ab' + iv_val = 1 ). + li_json->set( + iv_path = '/bc' + iv_val = 2 ). + li_json->set( + iv_path = '/xy' + iv_val = 3 ). + + li_json_new = zcl_abapgit_ajson=>create_from( + ii_source_json = li_json + ii_filter = me + ii_mapper = me ). + + CREATE OBJECT lo_nodes_exp. + lo_nodes_exp->add( ' | |object | | |2' ). + lo_nodes_exp->add( '/ |AB |num |1 | |0' ). + lo_nodes_exp->add( '/ |bc |num |2 | |0' ). + + cl_abap_unit_assert=>assert_equals( + act = li_json_new->mt_json_tree + exp = lo_nodes_exp->sorted( ) ). + + ENDMETHOD. + + METHOD opts_copying. + + DATA li_json TYPE REF TO zif_abapgit_ajson. + DATA li_json_new TYPE REF TO zif_abapgit_ajson. + + li_json = zcl_abapgit_ajson=>new( )->keep_item_order( ). + li_json->set( + iv_path = '/ab' + iv_val = 1 ). + + li_json_new = li_json->clone( ). + + cl_abap_unit_assert=>assert_equals( + act = li_json_new->opts( )-keep_item_order + exp = abap_true ). + + ENDMETHOD. + +ENDCLASS. diff --git a/src/json/zcl_abapgit_ajson_mapping.clas.abap b/src/json/zcl_abapgit_ajson_mapping.clas.abap index 08e8f838c..b3bed9c28 100644 --- a/src/json/zcl_abapgit_ajson_mapping.clas.abap +++ b/src/json/zcl_abapgit_ajson_mapping.clas.abap @@ -4,7 +4,16 @@ CLASS zcl_abapgit_ajson_mapping DEFINITION CREATE PUBLIC. PUBLIC SECTION. - CLASS-METHODS create_camel_case + + CONSTANTS: + BEGIN OF rename_by, + attr_name TYPE i VALUE 0, + full_path TYPE i VALUE 1, + pattern TYPE i VALUE 2, + " regex type i value 3, " TODO add if needed in future + END OF rename_by. + + CLASS-METHODS create_camel_case " DEPRECATED IMPORTING it_mapping_fields TYPE zif_abapgit_ajson_mapping=>ty_mapping_fields OPTIONAL iv_first_json_upper TYPE abap_bool DEFAULT abap_true @@ -23,12 +32,38 @@ CLASS zcl_abapgit_ajson_mapping DEFINITION RETURNING VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. - CLASS-METHODS create_field_mapping + CLASS-METHODS create_field_mapping " DEPRECATED IMPORTING it_mapping_fields TYPE zif_abapgit_ajson_mapping=>ty_mapping_fields RETURNING VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. + CLASS-METHODS create_rename + IMPORTING + it_rename_map TYPE zif_abapgit_ajson_mapping=>tty_rename_map + iv_rename_by TYPE i DEFAULT rename_by-attr_name + RETURNING + VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. + + CLASS-METHODS create_compound_mapper + IMPORTING + ii_mapper1 TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL + ii_mapper2 TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL + ii_mapper3 TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL + it_more TYPE zif_abapgit_ajson_mapping=>ty_table_of OPTIONAL + RETURNING + VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. + + CLASS-METHODS create_to_snake_case + RETURNING + VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. + + CLASS-METHODS create_to_camel_case + IMPORTING + iv_first_json_upper TYPE abap_bool DEFAULT abap_false + RETURNING + VALUE(ri_mapping) TYPE REF TO zif_abapgit_ajson_mapping. + PROTECTED SECTION. PRIVATE SECTION. @@ -67,6 +102,21 @@ CLASS zcl_abapgit_ajson_mapping IMPLEMENTATION. ENDMETHOD. + METHOD create_compound_mapper. + + DATA lt_queue TYPE zif_abapgit_ajson_mapping=>ty_table_of. + + APPEND ii_mapper1 TO lt_queue. + APPEND ii_mapper2 TO lt_queue. + APPEND ii_mapper3 TO lt_queue. + APPEND LINES OF it_more TO lt_queue. + DELETE lt_queue WHERE table_line IS INITIAL. + + CREATE OBJECT ri_mapping TYPE lcl_compound_mapper + EXPORTING + it_queue = lt_queue. + + ENDMETHOD. METHOD create_upper_case. @@ -75,4 +125,28 @@ CLASS zcl_abapgit_ajson_mapping IMPLEMENTATION. it_mapping_fields = it_mapping_fields. ENDMETHOD. + + METHOD create_rename. + + CREATE OBJECT ri_mapping TYPE lcl_rename + EXPORTING + it_rename_map = it_rename_map + iv_rename_by = iv_rename_by. + + ENDMETHOD. + + METHOD create_to_snake_case. + + CREATE OBJECT ri_mapping TYPE lcl_to_snake. + + ENDMETHOD. + + METHOD create_to_camel_case. + + CREATE OBJECT ri_mapping TYPE lcl_to_camel + EXPORTING + iv_first_json_upper = iv_first_json_upper. + + ENDMETHOD. + ENDCLASS. diff --git a/src/json/zcl_abapgit_ajson_mapping.clas.locals_def.abap b/src/json/zcl_abapgit_ajson_mapping.clas.locals_def.abap index bb89d9894..1768fe796 100644 --- a/src/json/zcl_abapgit_ajson_mapping.clas.locals_def.abap +++ b/src/json/zcl_abapgit_ajson_mapping.clas.locals_def.abap @@ -3,9 +3,6 @@ CLASS lcl_mapping_fields DEFINITION. PUBLIC SECTION. INTERFACES zif_abapgit_ajson_mapping. - ALIASES to_abap FOR zif_abapgit_ajson_mapping~to_abap. - ALIASES to_json FOR zif_abapgit_ajson_mapping~to_json. - METHODS constructor IMPORTING it_mapping_fields TYPE zif_abapgit_ajson_mapping~ty_mapping_fields OPTIONAL. @@ -17,6 +14,23 @@ CLASS lcl_mapping_fields DEFINITION. ENDCLASS. +CLASS lcl_rename DEFINITION. + + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_mapping. + + METHODS constructor + IMPORTING + it_rename_map TYPE zif_abapgit_ajson_mapping~tty_rename_map + iv_rename_by TYPE i. + + PROTECTED SECTION. + + PRIVATE SECTION. + DATA mt_rename_map TYPE zif_abapgit_ajson_mapping~tty_rename_map. + DATA mv_rename_by TYPE i. + +ENDCLASS. CLASS lcl_mapping_to_upper DEFINITION. @@ -69,3 +83,34 @@ CLASS lcl_mapping_camel DEFINITION. DATA mi_mapping_fields TYPE REF TO zif_abapgit_ajson_mapping. ENDCLASS. + +CLASS lcl_compound_mapper DEFINITION. + + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_mapping. + + METHODS constructor + IMPORTING + it_queue TYPE zif_abapgit_ajson_mapping=>ty_table_of. + + PROTECTED SECTION. + + PRIVATE SECTION. + DATA mt_queue TYPE zif_abapgit_ajson_mapping=>ty_table_of. + +ENDCLASS. + +CLASS lcl_to_snake DEFINITION. + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_mapping. +ENDCLASS. + +CLASS lcl_to_camel DEFINITION. + PUBLIC SECTION. + INTERFACES zif_abapgit_ajson_mapping. + METHODS constructor + IMPORTING + iv_first_json_upper TYPE abap_bool. + PRIVATE SECTION. + DATA mv_first_json_upper TYPE abap_bool. +ENDCLASS. diff --git a/src/json/zcl_abapgit_ajson_mapping.clas.locals_imp.abap b/src/json/zcl_abapgit_ajson_mapping.clas.locals_imp.abap index 23939c581..937b2618e 100644 --- a/src/json/zcl_abapgit_ajson_mapping.clas.locals_imp.abap +++ b/src/json/zcl_abapgit_ajson_mapping.clas.locals_imp.abap @@ -1,4 +1,4 @@ -CLASS lcl_mapping_fields IMPLEMENTATION. +CLASS lcl_mapping_fields IMPLEMENTATION. "DEPRECATED METHOD constructor. @@ -41,9 +41,58 @@ CLASS lcl_mapping_fields IMPLEMENTATION. ENDMETHOD. + METHOD zif_abapgit_ajson_mapping~rename_node. + + ENDMETHOD. ENDCLASS. +CLASS lcl_rename IMPLEMENTATION. + + METHOD constructor. + mt_rename_map = it_rename_map. + mv_rename_by = iv_rename_by. + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_abap. + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_json. + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~rename_node. + + DATA lv_full_path TYPE string. + DATA lv_pair_found TYPE abap_bool. + FIELD-SYMBOLS LIKE LINE OF mt_rename_map. + + CASE mv_rename_by. + WHEN zcl_abapgit_ajson_mapping=>rename_by-attr_name. + READ TABLE mt_rename_map ASSIGNING WITH TABLE KEY by_name COMPONENTS from = cv_name. + lv_pair_found = boolc( sy-subrc = 0 ). + WHEN zcl_abapgit_ajson_mapping=>rename_by-full_path. + lv_full_path = is_node-path && cv_name. + READ TABLE mt_rename_map ASSIGNING WITH TABLE KEY by_name COMPONENTS from = lv_full_path. + lv_pair_found = boolc( sy-subrc = 0 ). + WHEN zcl_abapgit_ajson_mapping=>rename_by-pattern. + lv_full_path = is_node-path && cv_name. + LOOP AT mt_rename_map ASSIGNING . + IF lv_full_path CP -from. + lv_pair_found = abap_true. + EXIT. + ENDIF. + ENDLOOP. + WHEN OTHERS. + lv_pair_found = abap_false. " No rename + ENDCASE. + + IF lv_pair_found = abap_true. + cv_name = -to. + ENDIF. + + ENDMETHOD. + +ENDCLASS. CLASS lcl_mapping_to_upper IMPLEMENTATION. @@ -76,6 +125,11 @@ CLASS lcl_mapping_to_upper IMPLEMENTATION. ENDMETHOD. + METHOD zif_abapgit_ajson_mapping~rename_node. + + cv_name = to_upper( cv_name ). + + ENDMETHOD. ENDCLASS. @@ -111,11 +165,16 @@ CLASS lcl_mapping_to_lower IMPLEMENTATION. ENDMETHOD. + METHOD zif_abapgit_ajson_mapping~rename_node. + + cv_name = to_lower( cv_name ). + + ENDMETHOD. ENDCLASS. -CLASS lcl_mapping_camel IMPLEMENTATION. +CLASS lcl_mapping_camel IMPLEMENTATION. "DEPRECATED METHOD constructor. @@ -179,5 +238,104 @@ CLASS lcl_mapping_camel IMPLEMENTATION. ENDMETHOD. + METHOD zif_abapgit_ajson_mapping~rename_node. + + ENDMETHOD. + +ENDCLASS. + +CLASS lcl_compound_mapper IMPLEMENTATION. + + METHOD constructor. + mt_queue = it_queue. + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~rename_node. + + DATA ls_node LIKE is_node. + DATA li_mapper LIKE LINE OF mt_queue. + + ls_node = is_node. + + LOOP AT mt_queue INTO li_mapper. + li_mapper->rename_node( + EXPORTING + is_node = ls_node + CHANGING + cv_name = cv_name ). + ls_node-name = cv_name. + ENDLOOP. + + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_abap. + + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_json. + + ENDMETHOD. + +ENDCLASS. + +CLASS lcl_to_snake IMPLEMENTATION. + + METHOD zif_abapgit_ajson_mapping~rename_node. + + REPLACE ALL OCCURRENCES OF REGEX `([a-z])([A-Z])` IN cv_name WITH `$1_$2`. + cv_name = to_lower( cv_name ). + + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_abap. + + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_json. + + ENDMETHOD. + +ENDCLASS. + +CLASS lcl_to_camel IMPLEMENTATION. + + METHOD constructor. + mv_first_json_upper = iv_first_json_upper. + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~rename_node. + + TYPES lty_token TYPE c LENGTH 255. + CONSTANTS lc_forced_underscore_marker TYPE c LENGTH 1 VALUE cl_abap_char_utilities=>horizontal_tab. + + DATA lt_tokens TYPE STANDARD TABLE OF lty_token. + DATA lv_from TYPE i. + FIELD-SYMBOLS LIKE LINE OF lt_tokens. + + IF mv_first_json_upper = abap_true. + lv_from = 1. + ELSE. + lv_from = 2. + ENDIF. + REPLACE ALL OCCURRENCES OF `__` IN cv_name WITH lc_forced_underscore_marker. " Force underscore + + SPLIT cv_name AT `_` INTO TABLE lt_tokens. + DELETE lt_tokens WHERE table_line IS INITIAL. + LOOP AT lt_tokens ASSIGNING FROM lv_from. + TRANSLATE +0(1) TO UPPER CASE. + ENDLOOP. + + CONCATENATE LINES OF lt_tokens INTO cv_name. + REPLACE ALL OCCURRENCES OF lc_forced_underscore_marker IN cv_name WITH `_`. + + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_abap. + + ENDMETHOD. + + METHOD zif_abapgit_ajson_mapping~to_json. + + ENDMETHOD. ENDCLASS. diff --git a/src/json/zcl_abapgit_ajson_mapping.clas.testclasses.abap b/src/json/zcl_abapgit_ajson_mapping.clas.testclasses.abap index 364fd3d37..18ee6e1cb 100644 --- a/src/json/zcl_abapgit_ajson_mapping.clas.testclasses.abap +++ b/src/json/zcl_abapgit_ajson_mapping.clas.testclasses.abap @@ -1,4 +1,4 @@ -CLASS ltcl_camel_case DEFINITION FINAL FOR TESTING +CLASS ltcl_test_mappers DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS. @@ -11,10 +11,21 @@ CLASS ltcl_camel_case DEFINITION FINAL FOR TESTING to_json_nested_table FOR TESTING RAISING zcx_abapgit_ajson_error, to_json_first_lower FOR TESTING RAISING zcx_abapgit_ajson_error. + METHODS: + to_snake FOR TESTING RAISING zcx_abapgit_ajson_error, + to_camel FOR TESTING RAISING zcx_abapgit_ajson_error, + to_camel_1st_upper FOR TESTING RAISING zcx_abapgit_ajson_error, + rename_by_attr FOR TESTING RAISING zcx_abapgit_ajson_error, + rename_by_path FOR TESTING RAISING zcx_abapgit_ajson_error, + rename_by_pattern FOR TESTING RAISING zcx_abapgit_ajson_error, + compound_mapper FOR TESTING RAISING zcx_abapgit_ajson_error, + test_to_upper FOR TESTING RAISING zcx_abapgit_ajson_error, + test_to_lower FOR TESTING RAISING zcx_abapgit_ajson_error. + ENDCLASS. -CLASS ltcl_camel_case IMPLEMENTATION. +CLASS ltcl_test_mappers IMPLEMENTATION. METHOD from_json_to_json. @@ -175,6 +186,165 @@ CLASS ltcl_camel_case IMPLEMENTATION. ENDMETHOD. + METHOD test_to_upper. + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>create_from( + ii_source_json = zcl_abapgit_ajson=>parse( '{"a":1,"b":{"c":2}}' ) + ii_mapper = zcl_abapgit_ajson_mapping=>create_upper_case( ) )->stringify( ) + exp = '{"A":1,"B":{"C":2}}' ). + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>parse( '{"a":1,"b":{"c":2}}' + )->map( zcl_abapgit_ajson_mapping=>create_upper_case( ) + )->stringify( ) + exp = '{"A":1,"B":{"C":2}}' ). + + ENDMETHOD. + + METHOD test_to_lower. + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>create_from( + ii_source_json = zcl_abapgit_ajson=>parse( '{"A":1,"B":{"C":2}}' ) + ii_mapper = zcl_abapgit_ajson_mapping=>create_lower_case( ) )->stringify( ) + exp = '{"a":1,"b":{"c":2}}' ). + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>parse( '{"A":1,"B":{"C":2}}' + )->map( zcl_abapgit_ajson_mapping=>create_lower_case( ) + )->stringify( ) + exp = '{"a":1,"b":{"c":2}}' ). + + ENDMETHOD. + + METHOD rename_by_attr. + + DATA lt_map TYPE zif_abapgit_ajson_mapping=>tty_rename_map. + FIELD-SYMBOLS LIKE LINE OF lt_map. + + APPEND INITIAL LINE TO lt_map ASSIGNING . + -from = 'a'. + -to = 'x'. + APPEND INITIAL LINE TO lt_map ASSIGNING . + -from = 'c'. + -to = 'y'. + APPEND INITIAL LINE TO lt_map ASSIGNING . + -from = 'd'. + -to = 'z'. + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>create_from( + ii_source_json = zcl_abapgit_ajson=>parse( '{"a":1,"b":{"c":2},"d":{"e":3}}' ) + ii_mapper = zcl_abapgit_ajson_mapping=>create_rename( lt_map + ) )->stringify( ) + exp = '{"b":{"y":2},"x":1,"z":{"e":3}}' ). + + ENDMETHOD. + + METHOD rename_by_path. + + DATA lt_map TYPE zif_abapgit_ajson_mapping=>tty_rename_map. + FIELD-SYMBOLS LIKE LINE OF lt_map. + + APPEND INITIAL LINE TO lt_map ASSIGNING . + -from = '/b/a'. + -to = 'x'. + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>create_from( + ii_source_json = zcl_abapgit_ajson=>parse( '{"a":1,"b":{"a":2},"c":{"a":3}}' ) + ii_mapper = zcl_abapgit_ajson_mapping=>create_rename( + it_rename_map = lt_map + iv_rename_by = zcl_abapgit_ajson_mapping=>rename_by-full_path + ) )->stringify( ) + exp = '{"a":1,"b":{"x":2},"c":{"a":3}}' ). + + ENDMETHOD. + + METHOD rename_by_pattern. + + DATA lt_map TYPE zif_abapgit_ajson_mapping=>tty_rename_map. + FIELD-SYMBOLS LIKE LINE OF lt_map. + + APPEND INITIAL LINE TO lt_map ASSIGNING . + -from = '/*/this*'. + -to = 'x'. + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>create_from( + ii_source_json = zcl_abapgit_ajson=>parse( '{"andthisnot":1,"b":{"thisone":2},"c":{"a":3}}' ) + ii_mapper = zcl_abapgit_ajson_mapping=>create_rename( + it_rename_map = lt_map + iv_rename_by = zcl_abapgit_ajson_mapping=>rename_by-pattern + ) )->stringify( ) + exp = '{"andthisnot":1,"b":{"x":2},"c":{"a":3}}' ). + + ENDMETHOD. + + METHOD compound_mapper. + + DATA lt_map TYPE zif_abapgit_ajson_mapping=>tty_rename_map. + FIELD-SYMBOLS LIKE LINE OF lt_map. + + APPEND INITIAL LINE TO lt_map ASSIGNING . + -from = '/b/a'. + -to = 'x'. + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>create_from( + ii_source_json = zcl_abapgit_ajson=>parse( '{"a":1,"b":{"a":2},"c":{"a":3}}' ) + ii_mapper = zcl_abapgit_ajson_mapping=>create_compound_mapper( + ii_mapper1 = zcl_abapgit_ajson_mapping=>create_rename( + it_rename_map = lt_map + iv_rename_by = zcl_abapgit_ajson_mapping=>rename_by-full_path ) + ii_mapper2 = zcl_abapgit_ajson_mapping=>create_upper_case( ) ) + )->stringify( ) + exp = '{"A":1,"B":{"X":2},"C":{"A":3}}' ). + + ENDMETHOD. + + METHOD to_snake. + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>create_from( + ii_source_json = zcl_abapgit_ajson=>parse( '{"aB":1,"BbC":2,"cD":{"xY":3},"ZZ":4}' ) + ii_mapper = zcl_abapgit_ajson_mapping=>create_to_snake_case( ) + )->stringify( ) + exp = '{"a_b":1,"bb_c":2,"c_d":{"x_y":3},"zz":4}' ). + + ENDMETHOD. + + METHOD to_camel. + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>create_from( + ii_source_json = zcl_abapgit_ajson=>parse( '{"a_b":1,"bb_c":2,"c_d":{"x_y":3},"zz":4}' ) + ii_mapper = zcl_abapgit_ajson_mapping=>create_to_camel_case( ) + )->stringify( ) + exp = '{"aB":1,"bbC":2,"cD":{"xY":3},"zz":4}' ). + + " Forced underscore + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>create_from( + ii_source_json = zcl_abapgit_ajson=>parse( '{"a__b":1}' ) + ii_mapper = zcl_abapgit_ajson_mapping=>create_to_camel_case( ) + )->stringify( ) + exp = '{"a_b":1}' ). + + ENDMETHOD. + + METHOD to_camel_1st_upper. + + cl_abap_unit_assert=>assert_equals( + act = zcl_abapgit_ajson=>create_from( + ii_source_json = zcl_abapgit_ajson=>parse( '{"aj_bc":1,"bb_c":2,"c_d":{"xq_yq":3},"zz":4}' ) + ii_mapper = zcl_abapgit_ajson_mapping=>create_to_camel_case( iv_first_json_upper = abap_true ) + )->stringify( ) + exp = '{"AjBc":1,"BbC":2,"CD":{"XqYq":3},"Zz":4}' ). + + ENDMETHOD. + ENDCLASS. diff --git a/src/json/zcx_abapgit_ajson_error.clas.abap b/src/json/zcx_abapgit_ajson_error.clas.abap index ce88ecbeb..a573370bf 100644 --- a/src/json/zcx_abapgit_ajson_error.clas.abap +++ b/src/json/zcx_abapgit_ajson_error.clas.abap @@ -43,11 +43,14 @@ public section. importing !IV_MSG type STRING !IV_LOCATION type STRING optional + !IS_NODE type ANY optional raising zcx_abapgit_ajson_error . - methods set_location + methods SET_LOCATION importing - iv_location type string. + !IV_LOCATION type STRING optional + !IS_NODE type ANY optional + preferred parameter IV_LOCATION . protected section. private section. types: @@ -64,7 +67,7 @@ ENDCLASS. CLASS zcx_abapgit_ajson_error IMPLEMENTATION. -method CONSTRUCTOR. + method CONSTRUCTOR. CALL METHOD SUPER->CONSTRUCTOR EXPORTING PREVIOUS = PREVIOUS @@ -82,51 +85,53 @@ if textid is initial. else. IF_T100_MESSAGE~T100KEY = TEXTID. endif. -endmethod. + endmethod. method raise. - data ls_msg type ty_message_parts. - data lv_tmp type string. + data lx type ref to zcx_abapgit_ajson_error. - if iv_location is initial. - lv_tmp = iv_msg. - else. - lv_tmp = iv_msg && | @{ iv_location }|. - endif. - ls_msg = lv_tmp. - - raise exception type zcx_abapgit_ajson_error - exporting - textid = zcx_ajson_error - message = iv_msg - location = iv_location - a1 = ls_msg-a1 - a2 = ls_msg-a2 - a3 = ls_msg-a3 - a4 = ls_msg-a4. + create object lx exporting message = iv_msg. + lx->set_location( + iv_location = iv_location + is_node = is_node ). + raise exception lx. endmethod. + method set_location. data ls_msg type ty_message_parts. + data lv_location type string. data lv_tmp type string. + field-symbols type string. + field-symbols type string. - if iv_location is initial. - lv_tmp = message. - else. - lv_tmp = message && | @{ iv_location }|. + if iv_location is not initial. + lv_location = iv_location. + elseif is_node is not initial. + assign component 'PATH' of structure is_node to . + assign component 'NAME' of structure is_node to . + if is assigned and is assigned. + lv_location = && . + endif. endif. + + if lv_location is not initial. + lv_tmp = message && | @{ lv_location }|. + else. + lv_tmp = message. + endif. + ls_msg = lv_tmp. - location = iv_location. + location = lv_location. a1 = ls_msg-a1. a2 = ls_msg-a2. a3 = ls_msg-a3. a4 = ls_msg-a4. endmethod. - ENDCLASS. diff --git a/src/json/zcx_abapgit_ajson_error.clas.testclasses.abap b/src/json/zcx_abapgit_ajson_error.clas.testclasses.abap index a2b710cd1..f97c19741 100644 --- a/src/json/zcx_abapgit_ajson_error.clas.testclasses.abap +++ b/src/json/zcx_abapgit_ajson_error.clas.testclasses.abap @@ -8,6 +8,7 @@ class ltcl_error definition methods raise for testing. methods raise_w_location for testing. + methods raise_w_node for testing. methods set_location for testing. endclass. @@ -50,6 +51,26 @@ class ltcl_error implementation. endmethod. + method raise_w_node. + + data lx type ref to zcx_abapgit_ajson_error. + data ls_node type zif_abapgit_ajson=>ty_node. + + ls_node-path = '/x/'. + ls_node-name = 'y'. + + try. + zcx_abapgit_ajson_error=>raise( iv_msg = 'a' + is_node = ls_node ). + cl_abap_unit_assert=>fail( ). + catch zcx_abapgit_ajson_error into lx. + cl_abap_unit_assert=>assert_equals( + exp = 'a @/x/y' + act = lx->get_text( ) ). + endtry. + + endmethod. + method set_location. data lx type ref to zcx_abapgit_ajson_error. diff --git a/src/json/zif_abapgit_ajson.intf.abap b/src/json/zif_abapgit_ajson.intf.abap index 99afb847a..cf24fe5ea 100644 --- a/src/json/zif_abapgit_ajson.intf.abap +++ b/src/json/zif_abapgit_ajson.intf.abap @@ -48,6 +48,27 @@ INTERFACE zif_abapgit_ajson DATA mt_json_tree TYPE ty_nodes_ts READ-ONLY. + " CLONING + METHODS clone + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + METHODS filter + IMPORTING + ii_filter TYPE REF TO zif_abapgit_ajson_filter + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + METHODS map + IMPORTING + ii_mapper TYPE REF TO zif_abapgit_ajson_mapping + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + " METHODS METHODS freeze. @@ -166,6 +187,14 @@ INTERFACE zif_abapgit_ajson RAISING zcx_abapgit_ajson_error. + METHODS setx + IMPORTING + iv_param TYPE string + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson + RAISING + zcx_abapgit_ajson_error. + METHODS set_boolean IMPORTING iv_path TYPE string diff --git a/src/json/zif_abapgit_ajson_mapping.intf.abap b/src/json/zif_abapgit_ajson_mapping.intf.abap index 6d7b1fc38..4b00401ea 100644 --- a/src/json/zif_abapgit_ajson_mapping.intf.abap +++ b/src/json/zif_abapgit_ajson_mapping.intf.abap @@ -2,7 +2,7 @@ INTERFACE zif_abapgit_ajson_mapping PUBLIC. TYPES: - BEGIN OF ty_mapping_field, + BEGIN OF ty_mapping_field, " deprecated, will be removed abap TYPE string, json TYPE string, END OF ty_mapping_field, @@ -10,18 +10,35 @@ INTERFACE zif_abapgit_ajson_mapping WITH UNIQUE SORTED KEY abap COMPONENTS abap WITH UNIQUE SORTED KEY json COMPONENTS json. - METHODS to_abap + TYPES: + BEGIN OF ty_rename, + from TYPE string, + to TYPE string, + END OF ty_rename, + tty_rename_map TYPE STANDARD TABLE OF ty_rename + WITH UNIQUE SORTED KEY by_name COMPONENTS from. + + TYPES: + ty_table_of TYPE STANDARD TABLE OF REF TO zif_abapgit_ajson_mapping. + + METHODS to_abap " deprecated, will be removed IMPORTING !iv_path TYPE string !iv_name TYPE string RETURNING VALUE(rv_result) TYPE string. - METHODS to_json + METHODS to_json " deprecated, will be removed IMPORTING !iv_path TYPE string !iv_name TYPE string RETURNING VALUE(rv_result) TYPE string. + METHODS rename_node + IMPORTING + !is_node TYPE zif_abapgit_ajson=>ty_node + CHANGING + !cv_name TYPE zif_abapgit_ajson=>ty_node-name. + ENDINTERFACE. diff --git a/src/objects/aff/zcl_abapgit_json_handler.clas.abap b/src/objects/aff/zcl_abapgit_json_handler.clas.abap index 550afe253..e3c222fd7 100644 --- a/src/objects/aff/zcl_abapgit_json_handler.clas.abap +++ b/src/objects/aff/zcl_abapgit_json_handler.clas.abap @@ -88,7 +88,7 @@ ENDCLASS. -CLASS ZCL_ABAPGIT_JSON_HANDLER IMPLEMENTATION. +CLASS zcl_abapgit_json_handler IMPLEMENTATION. METHOD deserialize. @@ -248,7 +248,7 @@ CLASS ZCL_ABAPGIT_JSON_HANDLER IMPLEMENTATION. lo_mapping = zcl_abapgit_ajson_mapping=>create_camel_case( iv_first_json_upper = abap_false ). - lo_ajson = zcl_abapgit_ajson=>create_empty( lo_mapping ). + lo_ajson = zcl_abapgit_ajson=>create_empty( ii_custom_mapping = lo_mapping ). lo_ajson->keep_item_order( ). lo_ajson->set( diff --git a/test/abap_transpile.json b/test/abap_transpile.json index a1f37fb57..fd6c26303 100644 --- a/test/abap_transpile.json +++ b/test/abap_transpile.json @@ -108,6 +108,7 @@ {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_json_to_abap", "method": "to_abap_array_of_arrays", "note": "Expected table to contain 2 rows, got 4"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_tab_hashed", "note": "Expected table to contain 4 rows, got 3"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_integrated", "method": "reader", "note": "Path not found @/false, keywords?"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "setx_float", "note": "DecFloat34"}, {"object": "ZCL_ABAPGIT_REQUIREMENT_HELPER", "class": "ltcl_lower_release", "method": "empty_patch", "note": "Void type: CVERS_SDU"}, {"object": "ZCL_ABAPGIT_REQUIREMENT_HELPER", "class": "ltcl_lower_release", "method": "lower_patch", "note": "Void type: CVERS_SDU"},