|
| 1 | +CLASS zcl_mjs_json DEFINITION PUBLIC FINAL. |
| 2 | + PUBLIC SECTION. |
| 3 | + CLASS-METHODS stringify |
| 4 | + IMPORTING is_val TYPE zif_mjs=>ty_value |
| 5 | + RETURNING VALUE(rv_json) TYPE string. |
| 6 | +ENDCLASS. |
| 7 | + |
| 8 | +CLASS zcl_mjs_json IMPLEMENTATION. |
| 9 | + |
| 10 | + METHOD stringify. |
| 11 | + CASE is_val-type. |
| 12 | + WHEN 0. " undefined → omit marker (caller handles) |
| 13 | + rv_json = ``. |
| 14 | + RETURN. |
| 15 | + WHEN 5. " null |
| 16 | + rv_json = `null`. |
| 17 | + WHEN 1. " number |
| 18 | + IF is_val-str = `NaN` OR is_val-str = `Infinity` OR is_val-str = `-Infinity`. |
| 19 | + rv_json = `null`. |
| 20 | + ELSE. |
| 21 | + rv_json = zcl_mjs_val=>to_string( is_val ). |
| 22 | + ENDIF. |
| 23 | + WHEN 3. " boolean |
| 24 | + rv_json = COND #( WHEN is_val-num <> 0 THEN `true` ELSE `false` ). |
| 25 | + WHEN 2. " string — quote and escape |
| 26 | + DATA lv_src TYPE string. |
| 27 | + DATA lv_out TYPE string. |
| 28 | + DATA lv_len TYPE i. |
| 29 | + DATA lv_idx TYPE i. |
| 30 | + DATA lv_ch TYPE string. |
| 31 | + DATA lv_cp TYPE i. |
| 32 | + DATA lv_hex2 TYPE x LENGTH 2. |
| 33 | + lv_src = is_val-str. |
| 34 | + lv_len = strlen( lv_src ). |
| 35 | + lv_out = `"`. |
| 36 | + lv_idx = 0. |
| 37 | + WHILE lv_idx < lv_len. |
| 38 | + lv_ch = substring( val = lv_src off = lv_idx len = 1 ). |
| 39 | + lv_hex2 = cl_abap_conv_out_ce=>uccp( lv_ch ). |
| 40 | + lv_cp = lv_hex2. |
| 41 | + IF lv_ch = `"`. |
| 42 | + lv_out = lv_out && `\"`. |
| 43 | + ELSEIF lv_ch = `\`. |
| 44 | + lv_out = lv_out && `\\`. |
| 45 | + ELSEIF lv_cp = 10. " newline |
| 46 | + lv_out = lv_out && `\n`. |
| 47 | + ELSEIF lv_cp = 13. " carriage return |
| 48 | + lv_out = lv_out && `\r`. |
| 49 | + ELSEIF lv_cp = 9. " tab |
| 50 | + lv_out = lv_out && `\t`. |
| 51 | + ELSEIF lv_cp < 32. " other control chars |
| 52 | + DATA lv_hex4_x TYPE x LENGTH 2. |
| 53 | + DATA lv_hex4 TYPE string. |
| 54 | + lv_hex4_x = lv_cp. |
| 55 | + lv_hex4 = lv_hex4_x. |
| 56 | + TRANSLATE lv_hex4 TO LOWER CASE. |
| 57 | + lv_out = lv_out && `\u` && lv_hex4. |
| 58 | + ELSE. |
| 59 | + lv_out = lv_out && lv_ch. |
| 60 | + ENDIF. |
| 61 | + lv_idx = lv_idx + 1. |
| 62 | + ENDWHILE. |
| 63 | + rv_json = lv_out && `"`. |
| 64 | + WHEN 6. " object |
| 65 | + IF is_val-obj IS NOT BOUND. |
| 66 | + rv_json = `{}`. |
| 67 | + RETURN. |
| 68 | + ENDIF. |
| 69 | + DATA lv_obj_out TYPE string. |
| 70 | + DATA lv_obj_first TYPE abap_bool VALUE abap_true. |
| 71 | + lv_obj_out = `{`. |
| 72 | + LOOP AT is_val-obj->props ASSIGNING FIELD-SYMBOL(<prop>). |
| 73 | + DATA(ls_pval) = zcl_mjs_val=>unbox_value( <prop>-val ). |
| 74 | + " skip undefined and function values |
| 75 | + IF ls_pval-type = 0 OR ls_pval-type = 4. |
| 76 | + CONTINUE. |
| 77 | + ENDIF. |
| 78 | + IF lv_obj_first = abap_false. |
| 79 | + lv_obj_out = lv_obj_out && `,`. |
| 80 | + ENDIF. |
| 81 | + lv_obj_out = lv_obj_out && `"` && <prop>-key && `":` && stringify( ls_pval ). |
| 82 | + lv_obj_first = abap_false. |
| 83 | + ENDLOOP. |
| 84 | + rv_json = lv_obj_out && `}`. |
| 85 | + WHEN 7. " array |
| 86 | + IF is_val-arr IS NOT BOUND. |
| 87 | + rv_json = `[]`. |
| 88 | + RETURN. |
| 89 | + ENDIF. |
| 90 | + DATA lv_arr_out TYPE string. |
| 91 | + DATA lv_arr_first TYPE abap_bool VALUE abap_true. |
| 92 | + DATA lv_arr_len TYPE i. |
| 93 | + DATA lv_arr_idx TYPE i. |
| 94 | + lv_arr_out = `[`. |
| 95 | + lv_arr_len = is_val-arr->length( ). |
| 96 | + lv_arr_idx = 0. |
| 97 | + WHILE lv_arr_idx < lv_arr_len. |
| 98 | + DATA(lr_elem) = is_val-arr->get_item( lv_arr_idx ). |
| 99 | + DATA lv_elem_json TYPE string. |
| 100 | + IF lr_elem IS BOUND. |
| 101 | + DATA(ls_elem) = zcl_mjs_val=>unbox_value( lr_elem ). |
| 102 | + IF ls_elem-type = 0 OR ls_elem-type = 4. |
| 103 | + lv_elem_json = `null`. " undefined/function in array → null |
| 104 | + ELSE. |
| 105 | + lv_elem_json = stringify( ls_elem ). |
| 106 | + ENDIF. |
| 107 | + ELSE. |
| 108 | + lv_elem_json = `null`. |
| 109 | + ENDIF. |
| 110 | + IF lv_arr_first = abap_false. |
| 111 | + lv_arr_out = lv_arr_out && `,`. |
| 112 | + ENDIF. |
| 113 | + lv_arr_out = lv_arr_out && lv_elem_json. |
| 114 | + lv_arr_first = abap_false. |
| 115 | + lv_arr_idx = lv_arr_idx + 1. |
| 116 | + ENDWHILE. |
| 117 | + rv_json = lv_arr_out && `]`. |
| 118 | + WHEN OTHERS. |
| 119 | + rv_json = `null`. |
| 120 | + ENDCASE. |
| 121 | + ENDMETHOD. |
| 122 | + |
| 123 | +ENDCLASS. |
0 commit comments