From 5a7e6bb57ac3888b6eefae5ed7599c5c49d7a7db Mon Sep 17 00:00:00 2001 From: Lukas Klausner Date: Thu, 28 Dec 2023 12:59:35 +0000 Subject: [PATCH 1/3] deserial. structure/table with value "null" In the deserializer, the value "null" was not accepted for structure and table types and an exception was raised. Now the value "null" is handled like an initial structure ("{}") or table ("[]"). --- src/z_ui2_json.clas.abap | 2 ++ src/z_ui2_json.clas.locals_imp.abap | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/z_ui2_json.clas.abap b/src/z_ui2_json.clas.abap index 003dd84..3211af6 100644 --- a/src/z_ui2_json.clas.abap +++ b/src/z_ui2_json.clas.abap @@ -2139,6 +2139,8 @@ ENDMETHOD. ENDIF. ELSEIF type_descr->kind EQ type_descr->kind_elem. eat_bool data. + ELSEIF type_descr->kind EQ type_descr->kind_struct OR type_descr->kind EQ type_descr->kind_table. + eat_null data. ELSE. eat_bool sdummy. throw_error. diff --git a/src/z_ui2_json.clas.locals_imp.abap b/src/z_ui2_json.clas.locals_imp.abap index 55f00e1..3f173a6 100644 --- a/src/z_ui2_json.clas.locals_imp.abap +++ b/src/z_ui2_json.clas.locals_imp.abap @@ -353,3 +353,14 @@ DEFINE eat_char. throw_error. ENDIF. END-OF-DEFINITION. + +DEFINE eat_null. + mark = offset. + while_offset_cs `nul`. + match = offset - mark. + IF json+mark(match) EQ `null` ##NO_TEXT. + CLEAR &1. + ELSE. + throw_error. + ENDIF. +END-OF-DEFINITION. From 1739c4ffca31e9481bf43c8f5368e1a2a354a041 Mon Sep 17 00:00:00 2001 From: Lukas Klausner Date: Mon, 8 Jan 2024 14:06:55 +0000 Subject: [PATCH 2/3] Unit test for null as table, structure, and string --- src/z_ui2_json.clas.testclasses.abap | 98 ++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/src/z_ui2_json.clas.testclasses.abap b/src/z_ui2_json.clas.testclasses.abap index 610f6cb..e4d842a 100644 --- a/src/z_ui2_json.clas.testclasses.abap +++ b/src/z_ui2_json.clas.testclasses.abap @@ -263,6 +263,10 @@ INHERITING FROM z_ui2_json. METHODS: serialize_formatted FOR TESTING. METHODS: serialize_cycle_reference FOR TESTING. + METHODS: deserialize_table_null FOR TESTING. + METHODS: deserialize_structure_null FOR TESTING. + METHODS: deserialize_string_null FOR TESTING. + ENDCLASS. "abap_unit_testclass * ---------------------------------------------------------------------- CLASS abap_unit_testclass IMPLEMENTATION. @@ -2868,4 +2872,98 @@ CLASS abap_unit_testclass IMPLEMENTATION. assoc_arrays_opt = abap_true ). ENDMETHOD. + METHOD deserialize_table_null. + + TYPES: BEGIN OF ty_test, + tab1 TYPE STANDARD TABLE OF string WITH EMPTY KEY, + BEGIN OF struc1, + field1 TYPE string, + END OF struc1, + string1 TYPE string, + END OF ty_test. + + DATA s_test2 TYPE ty_test. + + deserialize( + EXPORTING + json = '{"tab1":null,"struc1":{"field1":"hugo"},"string1":"u__u"}' + CHANGING + data = s_test2 + ). + + cl_abap_unit_assert=>assert_initial( + act = s_test2-tab1 ). + + cl_abap_unit_assert=>assert_equals( + exp = 'hugo' + act = s_test2-struc1-field1 ). + + cl_abap_unit_assert=>assert_equals( + exp = 'u__u' + act = s_test2-string1 ). + + ENDMETHOD. + + METHOD deserialize_structure_null. + + TYPES: BEGIN OF ty_test, + tab1 TYPE STANDARD TABLE OF string WITH EMPTY KEY, + BEGIN OF struc1, + field1 TYPE string, + END OF struc1, + string1 TYPE string, + END OF ty_test. + + DATA s_test2 TYPE ty_test. + + deserialize( + EXPORTING + json = '{"tab1":["hugo"],"struc1":null,"string1":"u__u"}' + CHANGING + data = s_test2 + ). + + cl_abap_unit_assert=>assert_equals( + exp = `hugo` + act = s_test2-tab1[ 1 ] ). + + cl_abap_unit_assert=>assert_initial( + act = s_test2-struc1 ). + + cl_abap_unit_assert=>assert_equals( + exp = 'u__u' + act = s_test2-string1 ). + ENDMETHOD. + + METHOD deserialize_string_null. + + TYPES: BEGIN OF ty_test2, + tab1 TYPE STANDARD TABLE OF string WITH EMPTY KEY, + BEGIN OF struc1, + field1 TYPE string, + END OF struc1, + string1 TYPE string, + END OF ty_test2. + + DATA s_test2 TYPE ty_test2. + + deserialize( + EXPORTING + json = '{"tab1":["hugo"],"struc1":{"field1":"hugo"},"string1":null}' + CHANGING + data = s_test2 + ). + + cl_abap_unit_assert=>assert_equals( + exp = `hugo` + act = s_test2-tab1[ 1 ] ). + + cl_abap_unit_assert=>assert_equals( + exp = 'hugo' + act = s_test2-struc1-field1 ). + + cl_abap_unit_assert=>assert_initial( + act = s_test2-string1 ). + ENDMETHOD. + ENDCLASS. "abap_unit_testclass From d4ad5a3ec4fcf420bd7735f0f91069112111af1d Mon Sep 17 00:00:00 2001 From: Lukas Klausner Date: Tue, 9 Jan 2024 16:29:47 +0000 Subject: [PATCH 3/3] correction of unit tests for "null" in strict mode in the first version, the unit tests were not using strict mode --- src/z_ui2_json.clas.testclasses.abap | 39 +++++++++++++++++++++------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/src/z_ui2_json.clas.testclasses.abap b/src/z_ui2_json.clas.testclasses.abap index e4d842a..238a602 100644 --- a/src/z_ui2_json.clas.testclasses.abap +++ b/src/z_ui2_json.clas.testclasses.abap @@ -263,9 +263,12 @@ INHERITING FROM z_ui2_json. METHODS: serialize_formatted FOR TESTING. METHODS: serialize_cycle_reference FOR TESTING. - METHODS: deserialize_table_null FOR TESTING. - METHODS: deserialize_structure_null FOR TESTING. - METHODS: deserialize_string_null FOR TESTING. + "! deserialize a null value for a table field in strict mode + METHODS deserialize_strict_table_null FOR TESTING. + "! deserialize a null value for a structure field in strict mode + METHODS deserialize_strict_struct_null FOR TESTING. + "! deserialize a null value for a string field in strict mode + METHODS deserialize_strict_string_null FOR TESTING. ENDCLASS. "abap_unit_testclass * ---------------------------------------------------------------------- @@ -2872,7 +2875,7 @@ CLASS abap_unit_testclass IMPLEMENTATION. assoc_arrays_opt = abap_true ). ENDMETHOD. - METHOD deserialize_table_null. + METHOD deserialize_strict_table_null. TYPES: BEGIN OF ty_test, tab1 TYPE STANDARD TABLE OF string WITH EMPTY KEY, @@ -2884,7 +2887,13 @@ CLASS abap_unit_testclass IMPLEMENTATION. DATA s_test2 TYPE ty_test. - deserialize( + DATA lo_json TYPE t_json. + CREATE OBJECT lo_json + EXPORTING + strict_mode = abap_true + pretty_name = pretty_mode-camel_case. + + lo_json->deserialize_int( EXPORTING json = '{"tab1":null,"struc1":{"field1":"hugo"},"string1":"u__u"}' CHANGING @@ -2904,7 +2913,7 @@ CLASS abap_unit_testclass IMPLEMENTATION. ENDMETHOD. - METHOD deserialize_structure_null. + METHOD deserialize_strict_struct_null. TYPES: BEGIN OF ty_test, tab1 TYPE STANDARD TABLE OF string WITH EMPTY KEY, @@ -2916,7 +2925,13 @@ CLASS abap_unit_testclass IMPLEMENTATION. DATA s_test2 TYPE ty_test. - deserialize( + DATA lo_json TYPE t_json. + CREATE OBJECT lo_json + EXPORTING + strict_mode = abap_true + pretty_name = pretty_mode-camel_case. + + lo_json->deserialize_int( EXPORTING json = '{"tab1":["hugo"],"struc1":null,"string1":"u__u"}' CHANGING @@ -2935,7 +2950,7 @@ CLASS abap_unit_testclass IMPLEMENTATION. act = s_test2-string1 ). ENDMETHOD. - METHOD deserialize_string_null. + METHOD deserialize_strict_string_null. TYPES: BEGIN OF ty_test2, tab1 TYPE STANDARD TABLE OF string WITH EMPTY KEY, @@ -2947,7 +2962,13 @@ CLASS abap_unit_testclass IMPLEMENTATION. DATA s_test2 TYPE ty_test2. - deserialize( + DATA lo_json TYPE t_json. + CREATE OBJECT lo_json + EXPORTING + strict_mode = abap_true + pretty_name = pretty_mode-camel_case. + + lo_json->deserialize_int( EXPORTING json = '{"tab1":["hugo"],"struc1":{"field1":"hugo"},"string1":null}' CHANGING