-
-
Save rplantiko/2282935 to your computer and use it in GitHub Desktop.
Added some module tests
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
REPORT ZZ_TEST_JSON_MYDOG. | |
* | |
class lcl_test definition for testing " #AU Risk_Level Harmless | |
inheriting from cl_aunit_assert. " #AU Duration Short | |
private section. | |
methods : | |
test_string for testing, | |
test_number for testing, | |
test_bool_true for testing, " <---- fails | |
test_bool_false for testing, " <---- fails | |
test_array_of_strings for testing, | |
test_hash_of_numbers for testing, | |
test_deep for testing. | |
endclass. | |
* | |
class lcl_test implementation. | |
* | |
method test_string. | |
data: lv_string type string. | |
perform json_to_data using 'Abc - Def' changing lv_string. | |
assert_equals( act = lv_string exp = 'Abc - Def' ). | |
endmethod. | |
method test_number. | |
data: lv_number type i. | |
perform json_to_data using '123456' changing lv_number. | |
assert_equals( act = lv_number exp = 123456 ). | |
endmethod. | |
method test_bool_true. | |
data: lv_flag type flag. | |
perform json_to_data using 'true' changing lv_flag. | |
assert_equals( act = lv_flag exp = 'X' ). | |
endmethod. | |
method test_bool_false. | |
data: lv_flag type flag. | |
perform json_to_data using 'false' changing lv_flag. | |
assert_equals( act = lv_flag exp = space ). | |
endmethod. | |
method test_array_of_strings. | |
data: lt_strings type stringtab, | |
lt_exp type stringtab. | |
append: 'a' to lt_exp, 'b' to lt_exp, 'c' to lt_exp. | |
perform json_to_data using '["a","b","c"]' changing lt_strings. | |
assert_equals( act = lt_strings exp = lt_exp ). | |
endmethod. | |
method test_hash_of_numbers. | |
types: begin of ty_hash, | |
a type i, | |
b type i, | |
c type i, | |
end of ty_hash. | |
data: ls_hash type ty_hash, | |
ls_exp type ty_hash. | |
ls_exp-a = 1. | |
ls_exp-b = 2. | |
ls_exp-c = 3. | |
perform json_to_data using '{"a":1,"b":2,"c":3}' changing ls_hash. | |
assert_equals( act = ls_hash exp = ls_exp ). | |
endmethod. | |
method test_deep. | |
types: begin of ty_hash, | |
a type i, | |
b type i, | |
c type i, | |
d type stringtab, | |
end of ty_hash, | |
ty_hash_tab type standard table of ty_hash. | |
data: ls_deep type ty_hash, | |
ls_exp type ty_hash, | |
lt_deep type ty_hash_tab, | |
lt_exp type ty_hash_tab. | |
clear ls_exp. | |
ls_exp-a = 1. | |
ls_exp-b = 2. | |
ls_exp-c = 3. | |
append 'e' to ls_exp-d. | |
append 'f' to ls_exp-d. | |
append 'g' to ls_exp-d. | |
append ls_exp to lt_exp. | |
clear ls_exp. | |
ls_exp-a = 4. | |
ls_exp-b = 5. | |
ls_exp-c = -6. | |
append 'h' to ls_exp-d. | |
append 'i' to ls_exp-d. | |
append ls_exp to lt_exp. | |
perform json_to_data using | |
'[{"a":1,"b":2,"c":3,"d":["e","f","g"]} , ' & | |
' {"a":4,"b":5,"c":-6,"d":["h","i"]} ]' | |
changing lt_deep. | |
assert_equals( act = lt_deep exp = lt_exp ). | |
endmethod. | |
endclass. | |
*&---------------------------------------------------------------------* | |
*& Form json_to_data | |
*&---------------------------------------------------------------------* | |
form json_to_data using json type string changing data type any. | |
data: lv_off type i. | |
data: lv_len type i. | |
data: lv_key type string. | |
data: lv_value type string. | |
data: lv_char type char1. "Current chacater | |
data: lv_pchar type char1. "Previous character | |
data: lv_instr type boole_d. "Indicator: cursor in string | |
data: lv_level type i. "Depth inside a block | |
data: lv_table type boole_d. | |
field-symbols: <fk> type string. | |
field-symbols: <data> type any. | |
field-symbols: <table> type any table. | |
field-symbols: <sotab> type sorted table. | |
field-symbols: <sttab> type standard table. | |
field-symbols: <line> type any. | |
data: ls_line type ref to data. | |
data: lr_td type ref to cl_abap_typedescr. | |
data: lr_ttd type ref to cl_abap_tabledescr. | |
* If the incoming json contains no '{}[]', we are dealing with | |
* a basic (scalar) value that is simply assigned to the data | |
* and then we return | |
if json na '{}[]'. | |
* Replace escape characters (TODO: Check if there are more!) | |
lv_value = json. | |
replace all occurrences of '\n' in lv_value with cl_abap_char_utilities=>newline. | |
replace all occurrences of '\t' in lv_value with cl_abap_char_utilities=>horizontal_tab. | |
replace all occurrences of '\f' in lv_value with cl_abap_char_utilities=>form_feed. | |
replace all occurrences of '\v' in lv_value with cl_abap_char_utilities=>vertical_tab. | |
replace all occurrences of '\b' in lv_value with cl_abap_char_utilities=>backspace. | |
replace all occurrences of '\\' in lv_value with '\'. | |
* TODO: Deal with specific data types, e.g. dates etc. | |
data = lv_value. | |
exit. | |
endif. | |
lv_len = strlen( json ). | |
* Check if we are dealing with a table | |
lr_td = cl_abap_typedescr=>describe_by_data( data ). | |
if lr_td->type_kind = cl_abap_typedescr=>typekind_table. | |
* This information is used later... | |
lv_table = 'X'. | |
assign data to <table>. | |
create data ls_line like line of <table>. | |
assign ls_line->* to <line>. | |
else. | |
lv_table = ' '. | |
endif. | |
* Reset counters/flags | |
lv_off = 0. | |
lv_instr = ' '. | |
lv_level = 0. | |
assign lv_key to <fk>. | |
while lv_off < lv_len. | |
lv_char = json+lv_off(1). | |
********************************************************************** | |
* IN STRING | |
********************************************************************** | |
* Character is in a string delimited by double quotes | |
if lv_instr = 'X'. | |
if lv_char = '"'. | |
* Switch out of delimited character string | |
if lv_pchar ne '\'. | |
lv_instr = ' '. | |
else. | |
concatenate <fk> lv_char into <fk> respecting blanks. | |
endif. | |
else. | |
concatenate <fk> lv_char into <fk> respecting blanks. | |
endif. | |
********************************************************************** | |
* OUTSIDE STRING | |
********************************************************************** | |
* Character is not in a string delimited by double quotes | |
else. | |
* On opening character, shift level up | |
if lv_char ca '{['. | |
add 1 to lv_level. | |
endif. | |
* When the value is contained in a {}/[], the entire value must | |
* be passed to the next level of processing | |
if lv_level > 1. | |
concatenate <fk> lv_char into <fk> respecting blanks. | |
else. | |
if lv_char ca '[{'. "<- Chars ignored outside of str | |
elseif lv_char = ':'. | |
assign lv_value to <fk>. | |
* The key collected up to now is assigned to the data member | |
translate lv_key to upper case. | |
shift lv_key left deleting leading space. | |
assign component lv_key of structure data to <data>. | |
* End of a key/value pair (we bump up against delimiter) - pass to next level | |
elseif ( lv_char = ',' or lv_char = '}' ) and lv_table = space. | |
* Process collected value | |
shift lv_value left deleting leading space. | |
perform json_to_data using lv_value changing <data>. | |
* Clear key and value | |
clear: lv_key, lv_value. | |
assign lv_key to <fk>. | |
clear: lv_key, lv_value. | |
* End of a key/value pair (we bump up against delimiter) - pass to next level | |
* But in table mode, we pass an instance of a row of the table, and afterward | |
* add it to the table | |
elseif ( lv_char = ',' or lv_char = ']' ) and lv_table = 'X'. | |
* Process collected value | |
* Inside array in JSON, there are no keys, only list of values, the collected | |
* value is in lv_key | |
shift lv_key left deleting leading space. | |
perform json_to_data using lv_key changing <line>. | |
* On return: if dealing with table, add the record to the table | |
lr_ttd ?= lr_td. | |
if lr_ttd->table_kind = cl_abap_tabledescr=>tablekind_sorted | |
or lr_ttd->table_kind = cl_abap_tabledescr=>tablekind_hashed. | |
assign data to <sotab>. | |
insert <line> into table <sotab>. | |
else. | |
assign data to <sttab>. | |
append <line> to <sttab>. | |
endif. | |
clear <line>. | |
* Clear key and value | |
clear: lv_key, lv_value. | |
assign lv_key to <fk>. | |
clear: lv_key, lv_value. | |
* Switch cursor into delimited string; consecutive characters | |
* are then treated as part of a key or value, even if they are | |
* special characters | |
elseif lv_char = '"'. | |
lv_instr = 'X'. | |
* Other chars processed as either key or value | |
else. | |
concatenate <fk> lv_char into <fk> respecting blanks. | |
endif. | |
endif. | |
* On closing character, shift level down again | |
if lv_char ca '}]'. | |
subtract 1 from lv_level. | |
endif. | |
* END: Are we in string or out? | |
endif. | |
lv_pchar = lv_char. | |
add 1 to lv_off. | |
endwhile. | |
endform. "json_to_data |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment