ajson, Automatic Update (#6341)

Co-authored-by: larshp <larshp@users.noreply.github.com>
Co-authored-by: Lars Hvam <larshp@hotmail.com>
This commit is contained in:
github-actions[bot] 2023-07-11 09:09:50 +02:00 committed by GitHub
parent 98fed3b641
commit b10276ffa5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 131 additions and 8 deletions

View File

@ -50,9 +50,10 @@ CLASS zcl_abapgit_ajson DEFINITION
CLASS-METHODS parse
IMPORTING
!iv_json TYPE string
!iv_freeze TYPE abap_bool DEFAULT abap_false
!ii_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL
!iv_json TYPE string
!iv_freeze TYPE abap_bool DEFAULT abap_false
!ii_custom_mapping TYPE REF TO zif_abapgit_ajson_mapping OPTIONAL
!iv_keep_item_order TYPE abap_bool DEFAULT abap_false
RETURNING
VALUE(ro_instance) TYPE REF TO zcl_abapgit_ajson
RAISING
@ -247,8 +248,11 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION.
CREATE OBJECT ro_instance.
CREATE OBJECT lo_parser.
ro_instance->mt_json_tree = lo_parser->parse( iv_json ).
ro_instance->mt_json_tree = lo_parser->parse(
iv_json = iv_json
iv_keep_item_order = iv_keep_item_order ).
ro_instance->mi_custom_mapping = ii_custom_mapping.
ro_instance->ms_opts-keep_item_order = iv_keep_item_order.
IF iv_freeze = abap_true.
ro_instance->freeze( ).
@ -592,6 +596,7 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION.
DATA ls_split_path TYPE zif_abapgit_ajson_types=>ty_path_name.
DATA lr_parent TYPE REF TO zif_abapgit_ajson_types=>ty_node.
DATA ls_deleted_node TYPE zif_abapgit_ajson_types=>ty_node.
DATA lv_item_order TYPE zif_abapgit_ajson_types=>ty_node-order.
read_only_watchdog( ).
@ -635,6 +640,7 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION.
ir_parent = lr_parent
iv_path = ls_split_path-path
iv_name = ls_split_path-name ).
lv_item_order = ls_deleted_node-order.
" convert to json
DATA lt_new_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt.
@ -644,12 +650,15 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION.
lv_array_index = lcl_utils=>validate_array_index(
iv_path = ls_split_path-path
iv_index = ls_split_path-name ).
ELSEIF lr_parent->type = zif_abapgit_ajson_types=>node_type-object
AND lv_item_order = 0 AND ms_opts-keep_item_order = abap_true.
lv_item_order = lr_parent->children + 1.
ENDIF.
IF iv_node_type IS NOT INITIAL.
lt_new_nodes = lcl_abap_to_json=>insert_with_type(
is_opts = ms_opts
iv_item_order = ls_deleted_node-order
iv_item_order = lv_item_order
iv_data = iv_val
iv_type = iv_node_type
iv_array_index = lv_array_index
@ -658,7 +667,7 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION.
ELSE.
lt_new_nodes = lcl_abap_to_json=>convert(
is_opts = ms_opts
iv_item_order = ls_deleted_node-order
iv_item_order = lv_item_order
iv_data = iv_val
iv_array_index = lv_array_index
is_prefix = ls_split_path
@ -725,7 +734,9 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION.
"Expect object/array, but no further checks, parser will catch errors
zif_abapgit_ajson~set(
iv_path = lv_path
iv_val = parse( lv_val ) ).
iv_val = parse(
iv_json = lv_val
iv_keep_item_order = ms_opts-keep_item_order ) ).
ELSE. " string
lv_last = strlen( lv_val ) - 1.
IF lv_val+0(1) = '"' AND lv_val+lv_last(1) = '"'.
@ -847,7 +858,7 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION.
RETURN.
ENDIF.
CLEAR: ls_item-path, ls_item-name. " this becomes a new root
CLEAR: ls_item-path, ls_item-name, ls_item-order. " this becomes a new root
INSERT ls_item INTO TABLE lo_section->mt_json_tree.
lv_path_pattern = lv_normalized_path && `*`.

View File

@ -189,6 +189,7 @@ CLASS lcl_json_parser DEFINITION FINAL.
METHODS parse
IMPORTING
iv_json TYPE string
iv_keep_item_order TYPE abap_bool DEFAULT abap_false
RETURNING
VALUE(rt_json_tree) TYPE zif_abapgit_ajson_types=>ty_nodes_tt
RAISING
@ -201,6 +202,7 @@ CLASS lcl_json_parser DEFINITION FINAL.
DATA mt_stack TYPE ty_stack_tt.
DATA mv_stack_path TYPE string.
DATA mv_keep_item_order TYPE abap_bool.
METHODS raise
IMPORTING
@ -231,6 +233,9 @@ CLASS lcl_json_parser IMPLEMENTATION.
DATA lx_sxml_parse TYPE REF TO cx_sxml_parse_error.
DATA lx_sxml TYPE REF TO cx_dynamic_check.
DATA lv_location TYPE string.
mv_keep_item_order = iv_keep_item_order.
TRY.
" TODO sane JSON check:
" JSON can be true,false,null,(-)digits
@ -248,6 +253,7 @@ CLASS lcl_json_parser IMPLEMENTATION.
iv_msg = |Json parsing error (SXML): { lx_sxml->get_text( ) }|
iv_location = '@PARSER' ).
ENDTRY.
ENDMETHOD.
METHOD _get_location.
@ -337,6 +343,9 @@ CLASS lcl_json_parser IMPLEMENTATION.
<item>-name = lo_attr->get_value( ).
ENDIF.
ENDLOOP.
IF mv_keep_item_order = abap_true.
<item>-order = lr_stack_top->children.
ENDIF.
ENDIF.
IF <item>-name IS INITIAL.
raise( 'Node without name (maybe not JSON)' ).
@ -1164,6 +1173,7 @@ CLASS lcl_abap_to_json DEFINITION FINAL.
io_json TYPE REF TO zif_abapgit_ajson
is_prefix TYPE zif_abapgit_ajson_types=>ty_path_name
iv_index TYPE i DEFAULT 0
iv_item_order TYPE i DEFAULT 0
CHANGING
ct_nodes TYPE zif_abapgit_ajson_types=>ty_nodes_tt
RAISING
@ -1324,6 +1334,7 @@ CLASS lcl_abap_to_json IMPLEMENTATION.
io_json = iv_data
is_prefix = is_prefix
iv_index = iv_index
iv_item_order = iv_item_order
CHANGING
ct_nodes = ct_nodes ).
ELSE.
@ -1351,6 +1362,7 @@ CLASS lcl_abap_to_json IMPLEMENTATION.
<dst>-path = is_prefix-path.
<dst>-name = is_prefix-name.
<dst>-index = iv_index.
<dst>-order = iv_item_order.
ELSE.
<dst>-path = is_prefix-path && is_prefix-name && <dst>-path.
ENDIF.

View File

@ -75,6 +75,7 @@ CLASS ltcl_parser_test DEFINITION FINAL
METHODS setup.
METHODS parse FOR TESTING RAISING zcx_abapgit_ajson_error.
METHODS parse_keeping_order FOR TESTING RAISING zcx_abapgit_ajson_error.
METHODS parse_string FOR TESTING RAISING zcx_abapgit_ajson_error.
METHODS parse_number FOR TESTING RAISING zcx_abapgit_ajson_error.
METHODS parse_float FOR TESTING RAISING zcx_abapgit_ajson_error.
@ -347,6 +348,67 @@ CLASS ltcl_parser_test IMPLEMENTATION.
ENDMETHOD.
METHOD parse_keeping_order.
DATA lo_cut TYPE REF TO lcl_json_parser.
DATA lt_act TYPE zif_abapgit_ajson_types=>ty_nodes_tt.
DATA lo_nodes TYPE REF TO lcl_nodes_helper.
CREATE OBJECT lo_nodes.
lo_nodes->add( ' | |object | | |8 |0' ).
lo_nodes->add( '/ |string |str |abc | |0 |1' ).
lo_nodes->add( '/ |number |num |123 | |0 |2' ).
lo_nodes->add( '/ |float |num |123.45 | |0 |3' ).
lo_nodes->add( '/ |boolean |bool |true | |0 |4' ).
lo_nodes->add( '/ |false |bool |false | |0 |5' ).
lo_nodes->add( '/ |null |null | | |0 |6' ).
lo_nodes->add( '/ |date |str |2020-03-15 | |0 |7' ).
lo_nodes->add( '/ |issues |array | | |2 |8' ).
lo_nodes->add( '/issues/ |1 |object | |1 |5 |0' ).
lo_nodes->add( '/issues/1/ |message |str |Indentation problem ... | |0 |1' ).
lo_nodes->add( '/issues/1/ |key |str |indentation | |0 |2' ).
lo_nodes->add( '/issues/1/ |start |object | | |2 |3' ).
lo_nodes->add( '/issues/1/start/ |row |num |4 | |0 |1' ).
lo_nodes->add( '/issues/1/start/ |col |num |3 | |0 |2' ).
lo_nodes->add( '/issues/1/ |end |object | | |2 |4' ).
lo_nodes->add( '/issues/1/end/ |row |num |4 | |0 |1' ).
lo_nodes->add( '/issues/1/end/ |col |num |26 | |0 |2' ).
lo_nodes->add( '/issues/1/ |filename |str |./zxxx.prog.abap | |0 |5' ).
lo_nodes->add( '/issues/ |2 |object | |2 |5 |0' ).
lo_nodes->add( '/issues/2/ |message |str |Remove space before XXX | |0 |1' ).
lo_nodes->add( '/issues/2/ |key |str |space_before_dot | |0 |2' ).
lo_nodes->add( '/issues/2/ |start |object | | |2 |3' ).
lo_nodes->add( '/issues/2/start/ |row |num |3 | |0 |1' ).
lo_nodes->add( '/issues/2/start/ |col |num |21 | |0 |2' ).
lo_nodes->add( '/issues/2/ |end |object | | |2 |4' ).
lo_nodes->add( '/issues/2/end/ |row |num |3 | |0 |1' ).
lo_nodes->add( '/issues/2/end/ |col |num |22 | |0 |2' ).
lo_nodes->add( '/issues/2/ |filename |str |./zxxx.prog.abap | |0 |5' ).
CREATE OBJECT lo_cut.
lt_act = lo_cut->parse(
iv_json = sample_json( )
iv_keep_item_order = abap_true ).
cl_abap_unit_assert=>assert_equals(
act = lt_act
exp = lo_nodes->mt_nodes ).
lt_act = lo_cut->parse(
iv_json = sample_json( |{ cl_abap_char_utilities=>newline }| )
iv_keep_item_order = abap_true ).
cl_abap_unit_assert=>assert_equals(
act = lt_act
exp = lo_nodes->mt_nodes ).
lt_act = lo_cut->parse(
iv_json = sample_json( |{ cl_abap_char_utilities=>cr_lf }| )
iv_keep_item_order = abap_true ).
cl_abap_unit_assert=>assert_equals(
act = lt_act
exp = lo_nodes->mt_nodes ).
ENDMETHOD.
METHOD duplicate_key.
DATA lo_cut TYPE REF TO lcl_json_parser.
@ -2101,6 +2163,7 @@ CLASS ltcl_writer_test DEFINITION FINAL
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 setx_complex_w_keep_order FOR TESTING RAISING zcx_abapgit_ajson_error.
METHODS set_with_type_slice
IMPORTING
@ -3324,6 +3387,43 @@ CLASS ltcl_writer_test IMPLEMENTATION.
ENDMETHOD.
METHOD setx_complex_w_keep_order.
DATA li_cut TYPE REF TO zif_abapgit_ajson.
DATA:
BEGIN OF ls_dummy,
f TYPE i VALUE 5,
e TYPE i VALUE 6,
END OF ls_dummy.
li_cut = zcl_abapgit_ajson=>new( iv_keep_item_order = abap_true ).
li_cut->setx( '/c:3' ).
li_cut->set(
iv_path = '/b'
iv_val = ls_dummy ).
li_cut->setx( '/a:1' ).
cl_abap_unit_assert=>assert_equals(
act = li_cut->stringify( )
exp = '{"c":3,"b":{"f":5,"e":6},"a":1}' ).
li_cut->setx( '/b:{"z":9,"y":8}' ).
cl_abap_unit_assert=>assert_equals(
act = li_cut->stringify( )
exp = '{"c":3,"b":{"z":9,"y":8},"a":1}' ).
" TODO: a subtle bug here. The '/b:{"z":9,"y":8}' creates a json internally
" without the ordering. It's just by chance that this UT passes, but the implementation
" does not guarantee it. The parser should be instructed to keep the order of the parsed json
li_cut->setx( '/0:9' ).
cl_abap_unit_assert=>assert_equals(
act = li_cut->stringify( )
exp = '{"c":3,"b":{"z":9,"y":8},"a":1,"0":9}' ).
ENDMETHOD.
ENDCLASS.