Skip to content

Commit 4e86d1b

Browse files
PL19.2: one more fix for PL19
- conversion exits on deserialize - type detection for timestamps in generate - unescaping of the escaped \ in JSON
1 parent d4510d6 commit 4e86d1b

File tree

3 files changed

+72
-56
lines changed

3 files changed

+72
-56
lines changed

src/z_ui2_json.clas.abap

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ CLASS z_ui2_json DEFINITION
281281
CLASS-DATA so_type_d TYPE REF TO cl_abap_elemdescr .
282282
CLASS-DATA so_type_t TYPE REF TO cl_abap_elemdescr .
283283
CLASS-DATA so_type_ts TYPE REF TO cl_abap_elemdescr .
284+
CLASS-DATA so_type_tsl TYPE REF TO cl_abap_elemdescr .
284285
CLASS-DATA so_type_t_json TYPE REF TO cl_abap_tabledescr .
285286
CLASS-DATA so_type_t_name_value TYPE REF TO cl_abap_tabledescr .
286287
CLASS-DATA so_regex_date TYPE REF TO cl_abap_regex.
@@ -541,6 +542,7 @@ CLASS Z_UI2_JSON IMPLEMENTATION.
541542
so_type_d = cl_abap_elemdescr=>get_d( ).
542543
so_type_t = cl_abap_elemdescr=>get_t( ).
543544
so_type_ts ?= cl_abap_typedescr=>describe_by_name( 'TIMESTAMP' ).
545+
so_type_tsl ?= cl_abap_typedescr=>describe_by_name( 'TIMESTAMPL' ).
544546
so_type_b ?= cl_abap_typedescr=>describe_by_name( 'ABAP_BOOL' ).
545547
so_type_t_json ?= cl_abap_typedescr=>describe_by_name( 'T_T_JSON' ).
546548
so_type_t_name_value ?= cl_abap_typedescr=>describe_by_name( 'T_T_NAME_JSON' ).
@@ -555,7 +557,7 @@ CLASS Z_UI2_JSON IMPLEMENTATION.
555557

556558
create_regexp so_regex_generate_normalize '[^0-9a-zA-Z_]{1,}'.
557559
create_regexp so_regex_generate_camel_case '([a-z])([A-Z])'.
558-
create_regexp so_regex_generate_type_detect '"(?:(?:\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:[\.,]\d{0,7})?(?:Z|(?:[+-]\d{2}:\d{2})))|(?:\d{4}-\d{2}-\d{2})|(?:\d{2}:\d{2}:\d{2}))"'.
560+
create_regexp so_regex_generate_type_detect '"(?:(?:\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:[\.,]\d{0,9})?(?:Z|(?:[+-]\d{2}:\d{2})))|(?:\d{4}-\d{2}-\d{2})|(?:\d{2}:\d{2}:\d{2}))"'.
559561

560562
create_regexp so_regex_unescape_spec_char '\\[rntfbu\\]'.
561563

@@ -675,7 +677,7 @@ CLASS Z_UI2_JSON IMPLEMENTATION.
675677

676678
" skip leading BOM signs till string, array, object, boolean or number
677679
length = strlen( lv_json ).
678-
while_offset_not_cs '"{[aeflnrstu0123456789+-eE.' lv_json.
680+
while_offset_not_cs '"{[aeflnrstu0123456789+-eE.' lv_json offset.
679681

680682
TRY.
681683
restore_type( EXPORTING json = lv_json length = length CHANGING data = data offset = offset ).
@@ -1175,7 +1177,6 @@ CLASS Z_UI2_JSON IMPLEMENTATION.
11751177
mark LIKE offset,
11761178
match LIKE offset,
11771179
data_opt LIKE data,
1178-
mlen TYPE i,
11791180
lo_type TYPE REF TO cl_abap_datadescr,
11801181
lo_table_type TYPE REF TO cl_abap_tabledescr,
11811182
lt_types TYPE SORTED TABLE OF REF TO cl_abap_datadescr WITH UNIQUE KEY table_line,
@@ -1248,31 +1249,47 @@ CLASS Z_UI2_JSON IMPLEMENTATION.
12481249
ENDIF.
12491250
WHEN '"'."string
12501251
FIND FIRST OCCURRENCE OF REGEX so_regex_generate_type_detect IN SECTION OFFSET offset
1251-
OF json MATCH LENGTH mlen.
1252+
OF json MATCH LENGTH match.
12521253
IF sy-subrc IS INITIAL.
1253-
CASE mlen.
1254+
CASE match.
12541255
WHEN 10. " time
12551256
restore_reference so_type_t.
12561257
WHEN 12. " date
12571258
restore_reference so_type_d.
1258-
WHEN OTHERS. " timestamp
1259-
restore_reference so_type_ts.
1259+
WHEN OTHERS. " timestamp(L)
1260+
IF json+offset(match) CA '.'. " TIMESTAMPL
1261+
restore_reference so_type_tsl.
1262+
ELSE.
1263+
restore_reference so_type_ts.
1264+
ENDIF.
12601265
ENDCASE.
12611266
ELSE.
12621267
restore_reference so_type_s.
12631268
ENDIF.
12641269
WHEN '-' OR '0' OR '1' OR '2' OR '3' OR '4' OR '5' OR '6' OR '7' OR '8' OR '9'. " number
1265-
IF json+offset CA '.Ee'.
1270+
IF offset EQ 0.
1271+
match = length.
1272+
ELSE.
1273+
mark = offset.
1274+
while_offset_cs '0123456789+-eE.' mark.
1275+
match = mark - offset.
1276+
ENDIF.
1277+
IF json+offset(match) CA '.Ee'.
12661278
restore_reference so_type_f.
1267-
ELSEIF length GT 9.
1279+
ELSEIF match GT 9.
12681280
restore_reference so_type_p.
12691281
ELSE.
12701282
restore_reference so_type_i.
12711283
ENDIF.
12721284
WHEN OTHERS.
1273-
eat_bool_string.
1274-
IF json+mark(match) EQ 'true' OR json+mark(match) EQ 'false'. "#EC NOTEXT
1275-
offset = mark. "need to restore after eat_bool_string
1285+
IF offset EQ 0.
1286+
match = length.
1287+
ELSE.
1288+
mark = offset.
1289+
while_offset_cs 'aeflnrstu' mark.
1290+
match = mark - offset.
1291+
ENDIF.
1292+
IF json+offset(match) EQ 'true' OR json+offset(match) EQ 'false'. "#EC NOTEXT
12761293
restore_reference so_type_b.
12771294
ELSE. "null or no match
12781295
CLEAR data.
@@ -1890,7 +1907,6 @@ CLASS Z_UI2_JSON IMPLEMENTATION.
18901907
ref_descr TYPE REF TO cl_abap_refdescr,
18911908
data_descr TYPE REF TO cl_abap_datadescr,
18921909
array_index TYPE i,
1893-
text_buf TYPE c LENGTH 128,
18941910
tstml TYPE timestampl,
18951911
date TYPE c LENGTH 8,
18961912
time TYPE c LENGTH 6,
@@ -2110,16 +2126,15 @@ CLASS Z_UI2_JSON IMPLEMENTATION.
21102126
TRY .
21112127
CALL FUNCTION lv_convexit
21122128
EXPORTING
2113-
input = sdummy
2129+
input = sdummy
21142130
IMPORTING
2115-
output = text_buf
2131+
output = data
21162132
EXCEPTIONS
2117-
error_message = 2
2118-
OTHERS = 1.
2119-
IF sy-subrc IS INITIAL.
2120-
data = text_buf.
2121-
RETURN.
2133+
OTHERS = 1.
2134+
IF sy-subrc IS NOT INITIAL.
2135+
CLEAR data.
21222136
ENDIF.
2137+
RETURN.
21232138
CATCH cx_root ##CATCH_ALL ##NO_HANDLER.
21242139
ENDTRY.
21252140
ENDIF.
@@ -2265,16 +2280,15 @@ CLASS Z_UI2_JSON IMPLEMENTATION.
22652280
eat_number sdummy.
22662281
CALL FUNCTION lv_convexit
22672282
EXPORTING
2268-
input = sdummy
2283+
input = sdummy
22692284
IMPORTING
2270-
output = text_buf
2285+
output = data
22712286
EXCEPTIONS
2272-
error_message = 2
2273-
OTHERS = 1.
2274-
IF sy-subrc IS INITIAL.
2275-
data = text_buf.
2276-
RETURN.
2287+
OTHERS = 1.
2288+
IF sy-subrc IS NOT INITIAL.
2289+
CLEAR data.
22772290
ENDIF.
2291+
RETURN.
22782292
CATCH cx_root ##CATCH_ALL ##NO_HANDLER.
22792293
ENDTRY.
22802294
ENDIF.
@@ -2494,7 +2508,7 @@ CLASS Z_UI2_JSON IMPLEMENTATION.
24942508
FIND FIRST OCCURRENCE OF '\\' IN unescaped+offset RESPECTING CASE.
24952509
IF sy-subrc IS INITIAL. " complex case - there are escaped "\"
24962510

2497-
FIND FIRST OCCURRENCE OF REGEX so_regex_unescape_spec_char IN SECTION OFFSET offset OF unescaped RESULTS lt_matches.
2511+
FIND ALL OCCURRENCES OF REGEX so_regex_unescape_spec_char IN SECTION OFFSET offset OF unescaped RESULTS lt_matches.
24982512
IF sy-subrc IS INITIAL.
24992513
lv_length = strlen( unescaped ).
25002514
LOOP AT lt_matches ASSIGNING <match>.

src/z_ui2_json.clas.locals_imp.abap

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -249,19 +249,19 @@ END-OF-DEFINITION.
249249
DEFINE while_offset_cs.
250250

251251
* >= 7.02 alternative
252-
offset = find_any_not_of( val = json sub = &1 off = offset ) ##NO_TEXT.
253-
IF offset EQ -1.
254-
offset = length.
252+
&2 = find_any_not_of( val = json sub = &1 off = &2 ) ##NO_TEXT.
253+
IF &2 EQ -1.
254+
&2 = length.
255255
ENDIF.
256256
* >= 7.02
257257

258258
* < 7.02
259-
* WHILE offset < length.
260-
* FIND FIRST OCCURRENCE OF json+offset(1) IN &1.
259+
* WHILE &2 < length.
260+
* FIND FIRST OCCURRENCE OF json+&2(1) IN &1.
261261
* IF sy-subrc IS NOT INITIAL.
262262
* EXIT.
263263
* ENDIF.
264-
* offset = offset + 1.
264+
* &2 = &2 + 1.
265265
* ENDWHILE.
266266
* < 7.02
267267

@@ -270,26 +270,26 @@ END-OF-DEFINITION.
270270
DEFINE while_offset_not_cs.
271271

272272
* >= 7.02 alternative
273-
offset = find_any_of( val = &2 sub = &1 off = offset ).
274-
IF offset EQ -1.
275-
offset = length.
273+
&3 = find_any_of( val = &2 sub = &1 off = &3 ).
274+
IF &3 EQ -1.
275+
&3 = length.
276276
ENDIF.
277277
* >= 7.02
278278

279279
* < 7.02
280-
* WHILE offset < length.
281-
* FIND FIRST OCCURRENCE OF &2+offset(1) IN &1.
280+
* WHILE &3 < length.
281+
* FIND FIRST OCCURRENCE OF &2+&3(1) IN &1.
282282
* IF sy-subrc IS INITIAL.
283283
* EXIT.
284284
* ENDIF.
285-
* offset = offset + 1.
285+
* &3 = &3 + 1.
286286
* ENDWHILE.
287287
* < 7.02
288288

289289
END-OF-DEFINITION.
290290

291291
DEFINE eat_white.
292-
while_offset_cs sv_white_space.
292+
while_offset_cs sv_white_space offset.
293293
IF offset GE length.
294294
throw_error.
295295
ENDIF.
@@ -323,19 +323,15 @@ END-OF-DEFINITION.
323323

324324
DEFINE eat_number.
325325
mark = offset.
326-
while_offset_cs '0123456789+-eE.'.
326+
while_offset_cs '0123456789+-eE.' offset.
327327
match = offset - mark.
328328
&1 = json+mark(match).
329329
END-OF-DEFINITION.
330330

331-
DEFINE eat_bool_string.
331+
DEFINE eat_bool.
332332
mark = offset.
333-
while_offset_cs 'aeflnrstu'.
333+
while_offset_cs 'aeflnrstu' offset.
334334
match = offset - mark.
335-
END-OF-DEFINITION.
336-
337-
DEFINE eat_bool.
338-
eat_bool_string.
339335
IF json+mark(match) EQ 'true' ##NO_TEXT.
340336
&1 = c_bool-true.
341337
ELSEIF json+mark(match) EQ 'false' ##NO_TEXT.

src/z_ui2_json.clas.testclasses.abap

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ CLASS lcl_util IMPLEMENTATION.
3434
METHOD class_constructor.
3535

3636
" support for ISO8601 => https://en.wikipedia.org/wiki/ISO_8601
37-
create_regexp so_regex_iso8601 '^(?:(\d{4})-?(\d{2})-?(\d{2}))?(?:T(\d{2}):?(\d{2})(?::?(\d{2}))?(?:[\.,](\d{0,7}))?(?:Z|(?:([+-])(\d{2})(?::?(\d{2}))?))?)?\s*$'.
37+
create_regexp so_regex_iso8601 '^(?:(\d{4})-?(\d{2})-?(\d{2}))?(?:T(\d{2}):?(\d{2})(?::?(\d{2}))?(?:[\.,](\d{0,9}))?(?:Z|(?:([+-])(\d{2})(?::?(\d{2}))?))?)?\s*$'.
3838

3939
ENDMETHOD.
4040

@@ -562,7 +562,7 @@ CLASS abap_unit_testclass IMPLEMENTATION.
562562
lv_exp LIKE lv_act.
563563

564564
ls_data-flag = abap_true.
565-
ls_data-char = '"TEST\"/C:\temp'.
565+
ls_data-char = '"TEST\"/C:\temp\'.
566566
ls_data-numc = 12345678.
567567
ls_data-string = 'ABCDEFG'.
568568
ls_data-xstring = ls_data-string.
@@ -609,7 +609,7 @@ CLASS abap_unit_testclass IMPLEMENTATION.
609609

610610
CLEAR ls_data-guid.
611611

612-
CONCATENATE `{"FLAG":true,"CHAR":"\"TEST\\\"/C:\\temp","NUMC":12345678,"STRING":"ABCDEFG","XSTRING":"q83v","INTEGER":42,"FLOAT":3.1415926535897900E+00,`
612+
CONCATENATE `{"FLAG":true,"CHAR":"\"TEST\\\"/C:\\temp\\","NUMC":12345678,"STRING":"ABCDEFG","XSTRING":"q83v","INTEGER":42,"FLOAT":3.1415926535897900E+00,`
613613
`"PACKED":3.141593,"HEX":"AAAAAAAAOt5osQ==","GUID":"","TSL":20151002134450.5545900,"TSL2":20191227160050.4540000,"TSL3":20191227160050.4540000,"TS":20160708123456,"DATE":"2016-07-08","TIME":"12:34:56","DATE_I":"","TIME_I":""}`
614614
INTO lv_exp.
615615
lv_act = serialize( data = ls_data ).
@@ -619,7 +619,7 @@ CLASS abap_unit_testclass IMPLEMENTATION.
619619
deserialize( EXPORTING json = lv_act CHANGING data = ls_data2 ).
620620
cl_aunit_assert=>assert_equals( act = ls_data2 exp = ls_data msg = 'Deserialization of data types fails' ).
621621

622-
CONCATENATE `{"FLAG":true,"CHAR":"\"TEST\\\"/C:\\temp","NUMC":12345678,"STRING":"ABCDEFG","XSTRING":"ABCDEF","INTEGER":42,"FLOAT":3.1415926535897900E+00,`
622+
CONCATENATE `{"FLAG":true,"CHAR":"\"TEST\\\"/C:\\temp\\","NUMC":12345678,"STRING":"ABCDEFG","XSTRING":"ABCDEF","INTEGER":42,"FLOAT":3.1415926535897900E+00,`
623623
`"PACKED":3.141593,"HEX":"0000000000003ADE68B1","GUID":"","TSL":20151002134450.5545900,"TSL2":20191227160050.4540000,"TSL3":20191227160050.4540000,"TS":20160708123456,"DATE":"2016-07-08","TIME":"12:34:56","DATE_I":"","TIME_I":""}`
624624
INTO lv_exp.
625625
lv_act = serialize( data = ls_data hex_as_base64 = abap_false ).
@@ -629,7 +629,7 @@ CLASS abap_unit_testclass IMPLEMENTATION.
629629
deserialize( EXPORTING json = lv_act hex_as_base64 = abap_false CHANGING data = ls_data2 ).
630630
cl_aunit_assert=>assert_equals( act = ls_data2 exp = ls_data msg = 'Deserialization of hex without base64 fails' ).
631631

632-
CONCATENATE `{"FLAG":true,"CHAR":"\"TEST\\\"/C:\\temp","NUMC":12345678,"STRING":"ABCDEFG","XSTRING":"q83v","INTEGER":42,"FLOAT":3.1415926535897900E+00,`
632+
CONCATENATE `{"FLAG":true,"CHAR":"\"TEST\\\"/C:\\temp\\","NUMC":12345678,"STRING":"ABCDEFG","XSTRING":"q83v","INTEGER":42,"FLOAT":3.1415926535897900E+00,`
633633
`"PACKED":3.141593,"HEX":"AAAAAAAAOt5osQ==","GUID":"","TSL":"2015-10-02T13:44:50.5545900Z","TSL2":"2019-12-27T16:00:50.4540000Z","TSL3":"2019-12-27T16:00:50.4540000Z","TS":"2016-07-08T12:34:56Z","DATE":"2016-07-08","TIME":"12:34:56",`
634634
`"DATE_I":"","TIME_I":""}`
635635
INTO lv_exp.
@@ -640,23 +640,23 @@ CLASS abap_unit_testclass IMPLEMENTATION.
640640
deserialize( EXPORTING json = lv_act CHANGING data = ls_data2 ).
641641
cl_aunit_assert=>assert_equals( act = ls_data2 exp = ls_data msg = 'Deserialization of timestamp in ISO8601 fails' ).
642642

643-
CONCATENATE `{"FLAG":true,"CHAR":"\"TEST\\\"\/C:\\temp","NUMC":12345678,"STRING":"ABCDEFG","XSTRING":"q83v","INTEGER":42,"FLOAT":3.1415926535897900E+00,`
643+
CONCATENATE `{"FLAG":true,"CHAR":"\"TEST\\\"\/C:\\temp\\","NUMC":12345678,"STRING":"ABCDEFG","XSTRING":"q83v","INTEGER":42,"FLOAT":3.1415926535897900E+00,`
644644
`"PACKED":3.141593,"HEX":"AAAAAAAAOt5osQ==","GUID":"","TSL":"2015-10-02T13:44:50.5545900Z","TSL2":"2019-12-27T16:00:50.4540000Z","TSL3":"20191227160050.4540000","TS":"2016-07-08T12:34:56Z","DATE":"2016-07-08","TIME":"12:34:56",`
645645
`"DATE_I":"","TIME_I":""}` INTO lv_act.
646646

647647
deserialize( EXPORTING json = lv_act CHANGING data = ls_data2 ).
648648
cl_aunit_assert=>assert_equals( act = ls_data2 exp = ls_data msg = 'Deserialization of redunant escapment fails' ).
649649

650650
" https://blogs.sap.com/2017/01/05/date-and-time-in-sap-gateway-foundation/
651-
CONCATENATE `{"FLAG":true,"CHAR":"\"TEST\\\"/C:\\temp","NUMC":12345678,"STRING":"ABCDEFG","XSTRING":"q83v","INTEGER":42,"FLOAT":3.1415926535897900E+00,`
651+
CONCATENATE `{"FLAG":true,"CHAR":"\"TEST\\\"/C:\\temp\\","NUMC":12345678,"STRING":"ABCDEFG","XSTRING":"q83v","INTEGER":42,"FLOAT":3.1415926535897900E+00,`
652652
`"PACKED":3.141593,"HEX":"AAAAAAAAOt5osQ==","GUID":"","TSL":"2015-10-02T13:44:50.5545900Z","TSL2":"\/Date(1577462450454)\/","TSL3":"\/Date(1577462450454)\/","TS":"\/Date(1467981296000)\/","DATE":"2016-07-08","TIME":"12:34:56",`
653653
`"DATE_I":"","TIME_I":""}` INTO lv_act.
654654

655655
deserialize( EXPORTING json = lv_act CHANGING data = ls_data2 ).
656656
cl_aunit_assert=>assert_equals( act = ls_data2 exp = ls_data msg = 'Deserialization of timestamp in Edm.DateTime fails' ).
657657

658658
" https://blogs.sap.com/2017/01/05/date-and-time-in-sap-gateway-foundation/
659-
CONCATENATE `{"FLAG":true,"CHAR":"\"TEST\\\"/C:\\temp","NUMC":12345678,"STRING":"ABCDEFG","XSTRING":"q83v","INTEGER":42,"FLOAT":3.1415926535897900E+00,`
659+
CONCATENATE `{"FLAG":true,"CHAR":"\"TEST\\\"/C:\\temp\\","NUMC":12345678,"STRING":"ABCDEFG","XSTRING":"q83v","INTEGER":42,"FLOAT":3.1415926535897900E+00,`
660660
`"PACKED":3.141593,"HEX":"AAAAAAAAOt5osQ==","GUID":"","TSL":"2015-10-02T13:44:50.5545900Z","TSL2":"\/Date(1577462450454)\/","TSL3":"\/Date(1577462450454)\/","TS":"\/Date(1467981296000)\/","DATE":"2016-07-08","TIME":"PT12H34M56S",`
661661
`"DATE_I":"","TIME_I":""}` INTO lv_act.
662662

@@ -701,6 +701,12 @@ CLASS abap_unit_testclass IMPLEMENTATION.
701701
deserialize( EXPORTING json = lv_act CHANGING data = lv_act_d ).
702702
cl_aunit_assert=>assert_equals( act = lv_act_d exp = '20170101' msg = 'Deserialization of date field in format 20170101 fails' ).
703703

704+
CONCATENATE '"' cl_abap_char_utilities=>cr_lf 'DATA(txt) = |Test_2\n|. "with nl' '"' cl_abap_char_utilities=>cr_lf INTO lv_exp.
705+
706+
lv_act = serialize( data = lv_exp ).
707+
deserialize( EXPORTING json = lv_act CHANGING data = lv_act ).
708+
cl_aunit_assert=>assert_equals( act = lv_act exp = lv_exp msg = 'Deserialization and serialization of complex escapment fails' ).
709+
704710
ENDMETHOD. "serialize_types
705711

706712
METHOD serialize_associative_array.

0 commit comments

Comments
 (0)