mirror of
https://github.com/abapGit/abapGit.git
synced 2025-04-30 20:03:20 +08:00
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:
parent
98fed3b641
commit
b10276ffa5
|
@ -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 && `*`.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user