From 647617a6a2007cd0b6f276c0fec17d9333330207 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 18 Apr 2022 08:58:02 +0200 Subject: [PATCH] ajson, Automatic Update (#5471) --- src/json/zcl_abapgit_ajson.clas.abap | 39 +++----- .../zcl_abapgit_ajson.clas.locals_imp.abap | 90 ++++++++++++++++++- .../zcl_abapgit_ajson.clas.testclasses.abap | 89 ++++++++++++++++-- src/json/zif_abapgit_ajson.intf.abap | 5 +- test/abap_transpile.json | 3 + 5 files changed, 193 insertions(+), 33 deletions(-) diff --git a/src/json/zcl_abapgit_ajson.clas.abap b/src/json/zcl_abapgit_ajson.clas.abap index f2806341d..1c596fb93 100644 --- a/src/json/zcl_abapgit_ajson.clas.abap +++ b/src/json/zcl_abapgit_ajson.clas.abap @@ -37,6 +37,7 @@ CLASS zcl_abapgit_ajson DEFINITION ALIASES: mt_json_tree FOR zif_abapgit_ajson~mt_json_tree, keep_item_order FOR zif_abapgit_ajson~keep_item_order, + format_datetime FOR zif_abapgit_ajson~format_datetime, freeze FOR zif_abapgit_ajson~freeze. CLASS-METHODS parse @@ -75,6 +76,7 @@ CLASS zcl_abapgit_ajson DEFINITION 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. METHODS get_item IMPORTING @@ -330,6 +332,11 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION. ENDMETHOD. + METHOD zif_abapgit_ajson~format_datetime. + mv_format_datetime = abap_true. + ri_json = me. + ENDMETHOD. + METHOD zif_abapgit_ajson~freeze. mv_read_only = abap_true. @@ -537,6 +544,7 @@ 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 iv_data = iv_val iv_type = iv_node_type @@ -544,6 +552,7 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION. 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 iv_data = iv_val is_prefix = ls_split_path @@ -574,6 +583,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 iv_data = iv_val iv_type = iv_node_type @@ -582,6 +592,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 iv_data = iv_val iv_array_index = lv_array_index @@ -617,9 +628,7 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION. ri_json = me. DATA lv_val TYPE string. - IF iv_val IS NOT INITIAL. - lv_val = iv_val+0(4) && '-' && iv_val+4(2) && '-' && iv_val+6(2). - ENDIF. + lv_val = lcl_abap_to_json=>format_date( iv_val ). zif_abapgit_ajson~set( iv_ignore_empty = abap_false @@ -670,30 +679,10 @@ CLASS zcl_abapgit_ajson IMPLEMENTATION. METHOD zif_abapgit_ajson~set_timestamp. - CONSTANTS lc_utc TYPE c LENGTH 6 VALUE 'UTC'. - - DATA: - lv_date TYPE d, - lv_time TYPE t, - lv_timestamp_iso TYPE string. - ri_json = me. - IF iv_val IS INITIAL. - " The zero value is January 1, year 1, 00:00:00.000000000 UTC. - lv_date = '00010101'. - ELSE. - - CONVERT TIME STAMP iv_val TIME ZONE lc_utc - INTO DATE lv_date TIME lv_time. - - ENDIF. - - lv_timestamp_iso = - lv_date+0(4) && '-' && lv_date+4(2) && '-' && lv_date+6(2) && - 'T' && - lv_time+0(2) && '-' && lv_time+2(2) && '-' && lv_time+4(2) && - 'Z'. + DATA lv_timestamp_iso TYPE string. + lv_timestamp_iso = lcl_abap_to_json=>format_timestamp( iv_val ). zif_abapgit_ajson~set( iv_ignore_empty = abap_false diff --git a/src/json/zcl_abapgit_ajson.clas.locals_imp.abap b/src/json/zcl_abapgit_ajson.clas.locals_imp.abap index 75663a7c6..b4280611c 100644 --- a/src/json/zcl_abapgit_ajson.clas.locals_imp.abap +++ b/src/json/zcl_abapgit_ajson.clas.locals_imp.abap @@ -149,6 +149,9 @@ CLASS lcl_json_parser IMPLEMENTATION. DATA lx_sxml TYPE REF TO cx_sxml_error. DATA lv_location TYPE string. TRY. + " TODO sane JSON check: + " JSON can be true,false,null,(-)digits + " or start from " or from { rt_json_tree = _parse( iv_json ). CATCH cx_sxml_parse_error INTO lx_sxml_parse. lv_location = _get_location( @@ -250,6 +253,9 @@ CLASS lcl_json_parser IMPLEMENTATION. ENDIF. ENDLOOP. ENDIF. + IF -name IS INITIAL. + raise( 'Node without name (maybe not JSON)' ). + ENDIF. ENDIF. GET REFERENCE OF INTO lr_stack_top. @@ -998,6 +1004,7 @@ CLASS lcl_abap_to_json DEFINITION FINAL. 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 RETURNING VALUE(rt_nodes) TYPE zif_abapgit_ajson=>ty_nodes_tt RAISING @@ -1011,11 +1018,28 @@ CLASS lcl_abap_to_json DEFINITION FINAL. 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 RETURNING VALUE(rt_nodes) TYPE zif_abapgit_ajson=>ty_nodes_tt RAISING zcx_abapgit_ajson_error. + CLASS-METHODS format_date + IMPORTING + iv_date TYPE d + RETURNING + VALUE(rv_str) TYPE string. + CLASS-METHODS format_time + IMPORTING + iv_time TYPE t + RETURNING + VALUE(rv_str) TYPE string. + CLASS-METHODS format_timestamp + IMPORTING + iv_ts TYPE timestamp + RETURNING + VALUE(rv_str) TYPE string. + CLASS-METHODS class_constructor. PRIVATE SECTION. @@ -1023,6 +1047,7 @@ CLASS lcl_abap_to_json DEFINITION FINAL. CLASS-DATA gv_ajson_absolute_type_name TYPE string. 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. METHODS convert_any IMPORTING @@ -1130,6 +1155,7 @@ 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->convert_any( EXPORTING @@ -1231,6 +1257,43 @@ CLASS lcl_abap_to_json IMPLEMENTATION. ENDMETHOD. + METHOD format_date. + IF iv_date IS NOT INITIAL. + rv_str = iv_date+0(4) && '-' && iv_date+4(2) && '-' && iv_date+6(2). + ENDIF. + ENDMETHOD. + + METHOD format_time. + IF iv_time IS NOT INITIAL. + rv_str = iv_time+0(2) && ':' && iv_time+2(2) && ':' && iv_time+4(2). + ENDIF. + ENDMETHOD. + + METHOD format_timestamp. + + CONSTANTS lc_utc TYPE c LENGTH 6 VALUE 'UTC'. + + DATA lv_date TYPE d. + DATA lv_time TYPE t. + + IF iv_ts IS INITIAL. + " The zero value is January 1, year 1, 00:00:00.000000000 UTC. + lv_date = '00010101'. + ELSE. + + CONVERT TIME STAMP iv_ts TIME ZONE lc_utc + INTO DATE lv_date TIME lv_time. + + ENDIF. + + rv_str = + lv_date+0(4) && '-' && lv_date+4(2) && '-' && lv_date+6(2) && + 'T' && + lv_time+0(2) && '-' && lv_time+2(2) && '-' && lv_time+4(2) && + 'Z'. + + ENDMETHOD. + METHOD convert_value. DATA ls_node LIKE LINE OF ct_nodes. @@ -1261,10 +1324,32 @@ CLASS lcl_abap_to_json IMPLEMENTATION. ELSE. ls_node-value = 'false'. ENDIF. - ELSEIF io_type->type_kind CO 'CNgXyDT'. " Char like, date/time, xstring + ELSEIF io_type->absolute_name = '\TYPE=TIMESTAMP'. + IF mv_format_datetime = abap_true. + ls_node-type = zif_abapgit_ajson=>node_type-string. + ls_node-value = format_timestamp( iv_data ). + ELSE. + ls_node-type = zif_abapgit_ajson=>node_type-number. + ls_node-value = |{ iv_data }|. + ENDIF. + ELSEIF io_type->type_kind CO 'CNgXy'. " Char like, xstring ls_node-type = zif_abapgit_ajson=>node_type-string. ls_node-value = |{ iv_data }|. - ELSEIF io_type->type_kind CO 'bsI8PaeF'. " Numeric + ELSEIF io_type->type_kind = 'D'. " Date + ls_node-type = zif_abapgit_ajson=>node_type-string. + IF mv_format_datetime = abap_true. + ls_node-value = format_date( iv_data ). + ELSE. + ls_node-value = |{ iv_data }|. + ENDIF. + ELSEIF io_type->type_kind = 'T'. " Time + ls_node-type = zif_abapgit_ajson=>node_type-string. + IF mv_format_datetime = abap_true. + ls_node-value = format_time( iv_data ). + ELSE. + ls_node-value = |{ iv_data }|. + ENDIF. + ELSEIF io_type->type_kind CO 'bsI8aeFP'. " Numeric ls_node-type = zif_abapgit_ajson=>node_type-number. ls_node-value = |{ iv_data }|. ELSE. @@ -1464,6 +1549,7 @@ 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->insert_value_with_type( EXPORTING diff --git a/src/json/zcl_abapgit_ajson.clas.testclasses.abap b/src/json/zcl_abapgit_ajson.clas.testclasses.abap index 1b9df4a85..1acd63ddd 100644 --- a/src/json/zcl_abapgit_ajson.clas.testclasses.abap +++ b/src/json/zcl_abapgit_ajson.clas.testclasses.abap @@ -84,6 +84,8 @@ CLASS ltcl_parser_test DEFINITION FINAL METHODS parse_date FOR TESTING RAISING zcx_abapgit_ajson_error. METHODS parse_bare_values FOR TESTING RAISING zcx_abapgit_ajson_error. METHODS parse_error FOR TESTING RAISING zcx_abapgit_ajson_error. + METHODS duplicate_key FOR TESTING RAISING zcx_abapgit_ajson_error. + METHODS non_json FOR TESTING RAISING zcx_abapgit_ajson_error. ENDCLASS. @@ -345,6 +347,36 @@ CLASS ltcl_parser_test IMPLEMENTATION. ENDMETHOD. + METHOD duplicate_key. + + DATA lo_cut TYPE REF TO lcl_json_parser. + DATA lx TYPE REF TO zcx_abapgit_ajson_error. + + TRY. + CREATE OBJECT lo_cut. + lo_cut->parse( '{ "a" = 1, "a" = 1 }' ). + cl_abap_unit_assert=>fail( ). + CATCH zcx_abapgit_ajson_error INTO lx. + cl_abap_unit_assert=>assert_not_initial( lx ). + ENDTRY. + + ENDMETHOD. + + METHOD non_json. + + DATA lo_cut TYPE REF TO lcl_json_parser. + DATA lx TYPE REF TO zcx_abapgit_ajson_error. + + TRY. + CREATE OBJECT lo_cut. + lo_cut->parse( 'X

Y

' ). + cl_abap_unit_assert=>fail( ). + CATCH zcx_abapgit_ajson_error INTO lx. + cl_abap_unit_assert=>assert_not_initial( lx ). + ENDTRY. + + ENDMETHOD. + ENDCLASS. ********************************************************************** @@ -1829,6 +1861,7 @@ CLASS ltcl_writer_test DEFINITION FINAL METHODS set_value FOR TESTING RAISING zcx_abapgit_ajson_error. METHODS ignore_empty FOR TESTING RAISING zcx_abapgit_ajson_error. METHODS set_obj FOR TESTING RAISING zcx_abapgit_ajson_error. + METHODS set_obj_w_date_time FOR TESTING RAISING zcx_abapgit_ajson_error. METHODS set_tab FOR TESTING RAISING zcx_abapgit_ajson_error. METHODS set_tab_hashed FOR TESTING RAISING zcx_abapgit_ajson_error. METHODS prove_path_exists FOR TESTING RAISING zcx_abapgit_ajson_error. @@ -2114,6 +2147,7 @@ CLASS ltcl_writer_test IMPLEMENTATION. BEGIN OF ls_struc, b TYPE string VALUE 'abc', c TYPE i VALUE 10, + d TYPE d VALUE '20220401', END OF ls_struc. lo_cut = zcl_abapgit_ajson=>create_empty( ). @@ -2121,10 +2155,11 @@ CLASS ltcl_writer_test IMPLEMENTATION. " Prepare source CREATE OBJECT lo_nodes. - lo_nodes->add( ' | |object | ||1' ). - lo_nodes->add( '/ |x |object | ||2' ). - lo_nodes->add( '/x/ |b |str |abc ||0' ). - lo_nodes->add( '/x/ |c |num |10 ||0' ). + lo_nodes->add( ' | |object | ||1' ). + lo_nodes->add( '/ |x |object | ||3' ). + lo_nodes->add( '/x/ |b |str |abc ||0' ). + lo_nodes->add( '/x/ |c |num |10 ||0' ). + lo_nodes->add( '/x/ |d |str |20220401 ||0' ). li_writer->set( iv_path = '/x' @@ -2135,6 +2170,44 @@ CLASS ltcl_writer_test IMPLEMENTATION. ENDMETHOD. + METHOD set_obj_w_date_time. + + DATA lo_nodes TYPE REF TO lcl_nodes_helper. + DATA lo_cut TYPE REF TO zif_abapgit_ajson. + DATA li_writer TYPE REF TO zif_abapgit_ajson. + + DATA: + BEGIN OF ls_struc, + d TYPE d VALUE '20220401', + d_empty TYPE d, + t TYPE t VALUE '200103', + t_empty TYPE t, + ts TYPE timestamp VALUE '20220401200103', + p(5) TYPE p DECIMALS 2 VALUE '123.45', + END OF ls_struc. + + lo_cut = zcl_abapgit_ajson=>create_empty( )->format_datetime( ). + li_writer = lo_cut. + + " Prepare source + CREATE OBJECT lo_nodes. + lo_nodes->add( ' | |object | ||6' ). + lo_nodes->add( '/ |d |str |2022-04-01 ||0' ). + lo_nodes->add( '/ |d_empty |str | ||0' ). + lo_nodes->add( '/ |t |str |20:01:03 ||0' ). + lo_nodes->add( '/ |t_empty |str | ||0' ). + lo_nodes->add( '/ |ts |str |2022-04-01T20-01-03Z ||0' ). + lo_nodes->add( '/ |p |num |123.45 ||0' ). + + li_writer->set( + iv_path = '/' + iv_val = ls_struc ). + cl_abap_unit_assert=>assert_equals( + act = lo_cut->mt_json_tree + exp = lo_nodes->sorted( ) ). + + ENDMETHOD. + METHOD set_tab. DATA lo_nodes TYPE REF TO lcl_nodes_helper. @@ -2577,14 +2650,20 @@ CLASS ltcl_writer_test IMPLEMENTATION. lo_cut = zcl_abapgit_ajson=>create_empty( ). li_writer = lo_cut. CREATE OBJECT lo_nodes_exp. - lo_nodes_exp->add( ' | |object | ||1' ). + lo_nodes_exp->add( ' | |object | ||2' ). lo_nodes_exp->add( '/ |a |str |2020-07-05 ||0' ). + lo_nodes_exp->add( '/ |b |str | ||0' ). lv_date = '20200705'. li_writer->set_date( iv_path = '/a' iv_val = lv_date ). + CLEAR lv_date. + li_writer->set_date( + iv_path = '/b' + iv_val = lv_date ). + cl_abap_unit_assert=>assert_equals( act = lo_cut->mt_json_tree exp = lo_nodes_exp->sorted( ) ). diff --git a/src/json/zif_abapgit_ajson.intf.abap b/src/json/zif_abapgit_ajson.intf.abap index 2b2eb25f5..969071872 100644 --- a/src/json/zif_abapgit_ajson.intf.abap +++ b/src/json/zif_abapgit_ajson.intf.abap @@ -1,7 +1,7 @@ INTERFACE zif_abapgit_ajson PUBLIC. - CONSTANTS version TYPE string VALUE 'v1.1.2'. "#EC NOTEXT + CONSTANTS version TYPE string VALUE 'v1.1.3'. "#EC NOTEXT CONSTANTS origin TYPE string VALUE 'https://github.com/sbcgua/ajson'. "#EC NOTEXT CONSTANTS license TYPE string VALUE 'MIT'. "#EC NOTEXT @@ -48,6 +48,9 @@ INTERFACE zif_abapgit_ajson METHODS keep_item_order RETURNING VALUE(ri_json) TYPE REF TO zif_abapgit_ajson. + METHODS format_datetime + RETURNING + VALUE(ri_json) TYPE REF TO zif_abapgit_ajson. " METHODS ex.reader diff --git a/test/abap_transpile.json b/test/abap_transpile.json index fd5043d51..c8416cbe6 100644 --- a/test/abap_transpile.json +++ b/test/abap_transpile.json @@ -151,9 +151,12 @@ {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_tab"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_tab_hashed", "note": "runtime error, SortByLengthZero"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "arrays"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "set_obj_w_date_time"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_writer_test", "method": "root_assignment"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_parser_test", "method": "parse_error"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_parser_test", "method": "duplicate_key", "note": "invalid json, should throw real abap exception"}, + {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_parser_test", "method": "non_json", "note": "invalid json, should throw real abap exception"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_integrated", "method": "reader", "note": "keyword? Path not found @/false"}, {"object": "ZCL_ABAPGIT_AJSON", "class": "ltcl_integrated", "method": "array_index", "note": "error ASSIGN, not a structure"},