mirror of
https://github.com/abapGit/abapGit.git
synced 2025-05-01 04:08:27 +08:00
ajson, Automatic Update (#7065)
Co-authored-by: larshp <larshp@users.noreply.github.com> Co-authored-by: Lars Hvam <larshp@hotmail.com>
This commit is contained in:
parent
436f23c899
commit
e83a31ebaf
|
@ -50,7 +50,7 @@ CLASS zcl_abapgit_ajson DEFINITION
|
|||
|
||||
CLASS-METHODS parse
|
||||
IMPORTING
|
||||
!iv_json TYPE string
|
||||
!iv_json TYPE any
|
||||
!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
|
||||
|
|
|
@ -20,27 +20,27 @@ INTERFACE lif_kind.
|
|||
|
||||
CONSTANTS:
|
||||
BEGIN OF numeric,
|
||||
int1 TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_int1,
|
||||
int2 TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_int2,
|
||||
int4 TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_int,
|
||||
int8 TYPE ty_kind VALUE '8', " cl_abap_tabledescr=>typekind_int8 not in lower releases
|
||||
float TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_float,
|
||||
packed TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_packed,
|
||||
decfloat16 TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_decfloat16,
|
||||
decfloat34 TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_decfloat34,
|
||||
int1 TYPE ty_kind VALUE cl_abap_typedescr=>typekind_int1,
|
||||
int2 TYPE ty_kind VALUE cl_abap_typedescr=>typekind_int2,
|
||||
int4 TYPE ty_kind VALUE cl_abap_typedescr=>typekind_int,
|
||||
int8 TYPE ty_kind VALUE '8', " cl_abap_typedescr=>typekind_int8 not in lower releases
|
||||
float TYPE ty_kind VALUE cl_abap_typedescr=>typekind_float,
|
||||
packed TYPE ty_kind VALUE cl_abap_typedescr=>typekind_packed,
|
||||
decfloat16 TYPE ty_kind VALUE cl_abap_typedescr=>typekind_decfloat16,
|
||||
decfloat34 TYPE ty_kind VALUE cl_abap_typedescr=>typekind_decfloat34,
|
||||
END OF numeric.
|
||||
|
||||
CONSTANTS:
|
||||
BEGIN OF texts,
|
||||
char TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_char,
|
||||
numc TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_num,
|
||||
string TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_string,
|
||||
char TYPE ty_kind VALUE cl_abap_typedescr=>typekind_char,
|
||||
numc TYPE ty_kind VALUE cl_abap_typedescr=>typekind_num,
|
||||
string TYPE ty_kind VALUE cl_abap_typedescr=>typekind_string,
|
||||
END OF texts.
|
||||
|
||||
CONSTANTS:
|
||||
BEGIN OF binary,
|
||||
hex TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_hex,
|
||||
xstring TYPE ty_kind VALUE cl_abap_tabledescr=>typekind_xstring,
|
||||
hex TYPE ty_kind VALUE cl_abap_typedescr=>typekind_hex,
|
||||
xstring TYPE ty_kind VALUE cl_abap_typedescr=>typekind_xstring,
|
||||
END OF binary.
|
||||
|
||||
CONSTANTS:
|
||||
|
@ -80,6 +80,25 @@ CLASS lcl_utils DEFINITION FINAL.
|
|||
iv_str TYPE string
|
||||
RETURNING
|
||||
VALUE(rv_xstr) TYPE xstring.
|
||||
CLASS-METHODS xstring_to_string_utf8
|
||||
IMPORTING
|
||||
iv_xstr TYPE xstring
|
||||
RETURNING
|
||||
VALUE(rv_str) TYPE string.
|
||||
CLASS-METHODS any_to_xstring
|
||||
IMPORTING
|
||||
iv_data TYPE any
|
||||
RETURNING
|
||||
VALUE(rv_xstr) TYPE xstring
|
||||
RAISING
|
||||
zcx_abapgit_ajson_error.
|
||||
CLASS-METHODS any_to_string
|
||||
IMPORTING
|
||||
iv_data TYPE any
|
||||
RETURNING
|
||||
VALUE(rv_str) TYPE string
|
||||
RAISING
|
||||
zcx_abapgit_ajson_error.
|
||||
|
||||
ENDCLASS.
|
||||
|
||||
|
@ -116,6 +135,37 @@ CLASS lcl_utils IMPLEMENTATION.
|
|||
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD xstring_to_string_utf8.
|
||||
|
||||
DATA lo_conv TYPE REF TO object.
|
||||
DATA lv_in_ce TYPE string.
|
||||
|
||||
lv_in_ce = 'CL_ABAP_CONV_IN_CE'.
|
||||
|
||||
TRY.
|
||||
CALL METHOD ('CL_ABAP_CONV_CODEPAGE')=>create_in
|
||||
RECEIVING
|
||||
instance = lo_conv.
|
||||
CALL METHOD lo_conv->('IF_ABAP_CONV_IN~CONVERT')
|
||||
EXPORTING
|
||||
source = iv_xstr
|
||||
RECEIVING
|
||||
result = rv_str.
|
||||
CATCH cx_sy_dyn_call_illegal_class.
|
||||
CALL METHOD (lv_in_ce)=>create
|
||||
EXPORTING
|
||||
encoding = 'UTF-8'
|
||||
RECEIVING
|
||||
conv = lo_conv.
|
||||
CALL METHOD lo_conv->('CONVERT')
|
||||
EXPORTING
|
||||
data = iv_xstr
|
||||
IMPORTING
|
||||
buffer = rv_str.
|
||||
ENDTRY.
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD validate_array_index.
|
||||
|
||||
IF NOT iv_index CO '0123456789'.
|
||||
|
@ -176,6 +226,74 @@ CLASS lcl_utils IMPLEMENTATION.
|
|||
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD any_to_xstring.
|
||||
" supports xstring, char, string, or string_table as input
|
||||
|
||||
DATA lo_type TYPE REF TO cl_abap_typedescr.
|
||||
DATA lo_table_type TYPE REF TO cl_abap_tabledescr.
|
||||
DATA lv_str TYPE string.
|
||||
|
||||
FIELD-SYMBOLS: <data> TYPE STANDARD TABLE.
|
||||
|
||||
lo_type = cl_abap_typedescr=>describe_by_data( iv_data ).
|
||||
|
||||
CASE lo_type->type_kind.
|
||||
WHEN lif_kind=>binary-xstring.
|
||||
rv_xstr = iv_data.
|
||||
WHEN lif_kind=>texts-string OR lif_kind=>texts-char.
|
||||
rv_xstr = string_to_xstring_utf8( iv_data ).
|
||||
WHEN lif_kind=>table.
|
||||
lo_table_type ?= lo_type.
|
||||
IF lo_table_type->table_kind <> cl_abap_tabledescr=>tablekind_std.
|
||||
zcx_abapgit_ajson_error=>raise( 'Unsupported type of input table (must be standard table)' ).
|
||||
ENDIF.
|
||||
TRY.
|
||||
ASSIGN iv_data TO <data>.
|
||||
lv_str = concat_lines_of( table = <data>
|
||||
sep = cl_abap_char_utilities=>newline ).
|
||||
rv_xstr = string_to_xstring_utf8( lv_str ).
|
||||
CATCH cx_root.
|
||||
zcx_abapgit_ajson_error=>raise( 'Error converting input table (should be string_table)' ).
|
||||
ENDTRY.
|
||||
WHEN OTHERS.
|
||||
zcx_abapgit_ajson_error=>raise( 'Unsupported type of input (must be char, string, string_table, or xstring)' ).
|
||||
ENDCASE.
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD any_to_string.
|
||||
" supports xstring, char, string, or string_table as input
|
||||
|
||||
DATA lo_type TYPE REF TO cl_abap_typedescr.
|
||||
DATA lo_table_type TYPE REF TO cl_abap_tabledescr.
|
||||
|
||||
FIELD-SYMBOLS: <data> TYPE STANDARD TABLE.
|
||||
|
||||
lo_type = cl_abap_typedescr=>describe_by_data( iv_data ).
|
||||
|
||||
CASE lo_type->type_kind.
|
||||
WHEN lif_kind=>binary-xstring.
|
||||
rv_str = xstring_to_string_utf8( iv_data ).
|
||||
WHEN lif_kind=>texts-string OR lif_kind=>texts-char.
|
||||
rv_str = iv_data.
|
||||
WHEN lif_kind=>table.
|
||||
lo_table_type ?= lo_type.
|
||||
IF lo_table_type->table_kind <> cl_abap_tabledescr=>tablekind_std.
|
||||
zcx_abapgit_ajson_error=>raise( 'Unsupported type of input table (must be standard table)' ).
|
||||
ENDIF.
|
||||
TRY.
|
||||
ASSIGN iv_data TO <data>.
|
||||
rv_str = concat_lines_of( table = <data>
|
||||
sep = cl_abap_char_utilities=>newline ).
|
||||
CATCH cx_root.
|
||||
zcx_abapgit_ajson_error=>raise( 'Error converting input table (should be string_table)' ).
|
||||
ENDTRY.
|
||||
WHEN OTHERS.
|
||||
zcx_abapgit_ajson_error=>raise( 'Unsupported type of input (must be char, string, string_table, or xstring)' ).
|
||||
ENDCASE.
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
|
@ -188,7 +306,7 @@ CLASS lcl_json_parser DEFINITION FINAL.
|
|||
|
||||
METHODS parse
|
||||
IMPORTING
|
||||
iv_json TYPE string
|
||||
iv_json TYPE any
|
||||
iv_keep_item_order TYPE abap_bool DEFAULT abap_false
|
||||
RETURNING
|
||||
VALUE(rt_json_tree) TYPE zif_abapgit_ajson_types=>ty_nodes_tt
|
||||
|
@ -212,7 +330,7 @@ CLASS lcl_json_parser DEFINITION FINAL.
|
|||
|
||||
METHODS _parse
|
||||
IMPORTING
|
||||
iv_json TYPE string
|
||||
iv_json TYPE xstring
|
||||
RETURNING
|
||||
VALUE(rt_json_tree) TYPE zif_abapgit_ajson_types=>ty_nodes_tt
|
||||
RAISING
|
||||
|
@ -233,17 +351,20 @@ 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.
|
||||
DATA lv_json TYPE xstring.
|
||||
|
||||
mv_keep_item_order = iv_keep_item_order.
|
||||
|
||||
lv_json = lcl_utils=>any_to_xstring( iv_json ).
|
||||
|
||||
TRY.
|
||||
" TODO sane JSON check:
|
||||
" JSON can be true,false,null,(-)digits
|
||||
" or start from " or from {
|
||||
rt_json_tree = _parse( iv_json ).
|
||||
rt_json_tree = _parse( lv_json ).
|
||||
CATCH cx_sxml_parse_error INTO lx_sxml_parse.
|
||||
lv_location = _get_location(
|
||||
iv_json = iv_json
|
||||
iv_json = lcl_utils=>any_to_string( iv_json )
|
||||
iv_offset = lx_sxml_parse->xml_offset ).
|
||||
zcx_abapgit_ajson_error=>raise(
|
||||
iv_msg = |Json parsing error (SXML): { lx_sxml_parse->get_text( ) }|
|
||||
|
@ -305,7 +426,7 @@ CLASS lcl_json_parser IMPLEMENTATION.
|
|||
IF iv_json IS INITIAL.
|
||||
RETURN.
|
||||
ENDIF.
|
||||
lo_reader = cl_sxml_string_reader=>create( lcl_utils=>string_to_xstring_utf8( iv_json ) ).
|
||||
lo_reader = cl_sxml_string_reader=>create( iv_json ).
|
||||
|
||||
" TODO: self protection, check non-empty, check starting from object ...
|
||||
|
||||
|
|
|
@ -85,6 +85,10 @@ 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 parse_input_xstring FOR TESTING RAISING zcx_abapgit_ajson_error.
|
||||
METHODS parse_input_string FOR TESTING RAISING zcx_abapgit_ajson_error.
|
||||
METHODS parse_input_string_table FOR TESTING RAISING zcx_abapgit_ajson_error.
|
||||
METHODS parse_input_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.
|
||||
|
||||
|
@ -248,6 +252,78 @@ CLASS ltcl_parser_test IMPLEMENTATION.
|
|||
exp = mo_nodes->mt_nodes ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD parse_input_xstring.
|
||||
mo_nodes->add( ' | |object | | |1' ).
|
||||
mo_nodes->add( '/ |string |str |abc | |0' ).
|
||||
|
||||
DATA lt_act TYPE zif_abapgit_ajson_types=>ty_nodes_tt.
|
||||
DATA lv_xstr TYPE xstring.
|
||||
|
||||
lv_xstr = '7B22737472696E67223A2022616263227D0A'.
|
||||
lt_act = mo_cut->parse( lv_xstr ).
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
act = lt_act
|
||||
exp = mo_nodes->mt_nodes ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD parse_input_string.
|
||||
mo_nodes->add( ' | |object | | |1' ).
|
||||
mo_nodes->add( '/ |string |str |abc | |0' ).
|
||||
|
||||
DATA lt_act TYPE zif_abapgit_ajson_types=>ty_nodes_tt.
|
||||
DATA lv_str TYPE string.
|
||||
|
||||
lv_str = `{"string": "abc"}`.
|
||||
lt_act = mo_cut->parse( lv_str ).
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
act = lt_act
|
||||
exp = mo_nodes->mt_nodes ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD parse_input_string_table.
|
||||
mo_nodes->add( ' | |object | | |2' ).
|
||||
mo_nodes->add( '/ |string |str |abc | |0' ).
|
||||
mo_nodes->add( '/ |number |num |123 | |0' ).
|
||||
|
||||
DATA lt_act TYPE zif_abapgit_ajson_types=>ty_nodes_tt.
|
||||
DATA lt_json TYPE string_table.
|
||||
|
||||
INSERT `{` INTO TABLE lt_json.
|
||||
INSERT `"string": "abc",` INTO TABLE lt_json.
|
||||
INSERT `"number": 123` INTO TABLE lt_json.
|
||||
INSERT `}` INTO TABLE lt_json.
|
||||
|
||||
lt_act = mo_cut->parse( lt_json ).
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
act = lt_act
|
||||
exp = mo_nodes->mt_nodes ).
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD parse_input_error.
|
||||
|
||||
DATA lo_cut TYPE REF TO lcl_json_parser.
|
||||
DATA lx TYPE REF TO zcx_abapgit_ajson_error.
|
||||
DATA lv_numc TYPE n LENGTH 10.
|
||||
DATA lt_hashed TYPE HASHED TABLE OF string WITH UNIQUE DEFAULT KEY.
|
||||
|
||||
CREATE OBJECT lo_cut.
|
||||
|
||||
TRY.
|
||||
lo_cut->parse( lv_numc ).
|
||||
cl_abap_unit_assert=>fail( ).
|
||||
CATCH zcx_abapgit_ajson_error INTO lx.
|
||||
cl_abap_unit_assert=>assert_not_initial( lx ).
|
||||
ENDTRY.
|
||||
|
||||
TRY.
|
||||
lo_cut->parse( lt_hashed ).
|
||||
cl_abap_unit_assert=>fail( ).
|
||||
CATCH zcx_abapgit_ajson_error INTO lx.
|
||||
cl_abap_unit_assert=>assert_not_initial( lx ).
|
||||
ENDTRY.
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD sample_json.
|
||||
|
||||
rv_json =
|
||||
|
@ -2401,6 +2477,7 @@ CLASS ltcl_writer_test DEFINITION FINAL
|
|||
METHODS set_bool_tab FOR TESTING RAISING zcx_abapgit_ajson_error.
|
||||
METHODS set_str FOR TESTING RAISING zcx_abapgit_ajson_error.
|
||||
METHODS set_int FOR TESTING RAISING zcx_abapgit_ajson_error.
|
||||
METHODS set_number FOR TESTING RAISING zcx_abapgit_ajson_error.
|
||||
METHODS set_date FOR TESTING RAISING zcx_abapgit_ajson_error.
|
||||
METHODS set_timestamp FOR TESTING RAISING zcx_abapgit_ajson_error.
|
||||
METHODS read_only FOR TESTING RAISING zcx_abapgit_ajson_error.
|
||||
|
@ -3241,6 +3318,27 @@ CLASS ltcl_writer_test IMPLEMENTATION.
|
|||
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD set_number.
|
||||
|
||||
DATA lo_nodes_exp TYPE REF TO lcl_nodes_helper.
|
||||
DATA li_json TYPE REF TO zif_abapgit_ajson.
|
||||
DATA lv_p TYPE p LENGTH 5 DECIMALS 2 VALUE '123.45'.
|
||||
|
||||
li_json = zcl_abapgit_ajson=>create_empty( ).
|
||||
CREATE OBJECT lo_nodes_exp.
|
||||
lo_nodes_exp->add( ' | |object | ||1' ).
|
||||
lo_nodes_exp->add( '/ |a |num |123.45 ||0' ).
|
||||
|
||||
li_json->set(
|
||||
iv_path = '/a'
|
||||
iv_val = lv_p ).
|
||||
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
act = li_json->mt_json_tree
|
||||
exp = lo_nodes_exp->sorted( ) ).
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
METHOD set_date.
|
||||
|
||||
DATA lo_cut TYPE REF TO zcl_abapgit_ajson.
|
||||
|
|
Loading…
Reference in New Issue
Block a user