RESTFUL方式
SE24新建异常类:ZCX_JSON
SE24新建类:ZCL_JSON_HANDLER
点击基于源代码复制以下代码
1 class ZCL_JSON_HANDLER definition 2 public 3 create public . 4 5 public section. 6 type-pools ABAP . 7 type-pools JS . 8 9 *"* public components of class ZCL_JSON_HANDLER 10 *"* do not include other source files here!!! 11 interfaces IF_HTTP_EXTENSION . 12 13 constants XNL type ABAP_CHAR1 value %_NEWLINE ##NO_TEXT. 14 constants XCRLF type ABAP_CR_LF value %_CR_LF ##NO_TEXT. 15 data MY_SERVICE type STRING . 16 data MY_URL type STRING . 17 18 class-methods ABAP2JSON 19 importing 20 !ABAP_DATA type DATA 21 !NAME type STRING optional 22 !UPCASE type XFELD optional 23 !CAMELCASE type XFELD optional 24 !CAMELCASE_NAMES type STRINGTAB optional 25 returning 26 value(JSON_STRING) type STRING 27 exceptions 28 ERROR_IN_DATA_DESCRIPTION . 29 class-methods ABAP2PERL 30 importing 31 !ABAP_DATA type DATA 32 !NAME type STRING optional 33 !UPCASE type XFELD optional 34 returning 35 value(PERL_STRING) type STRING 36 exceptions 37 ERROR_IN_DATA_DESCRIPTION . 38 class-methods ABAP2XML 39 importing 40 !ABAP_DATA type DATA 41 !NAME type STRING optional 42 !WITH_XML_HEADER type ABAP_BOOL default ABAP_FALSE 43 !UPCASE type XFELD optional 44 !NAME_ATR type STRING optional 45 returning 46 value(XML_STRING) type STRING . 47 class-methods ABAP2YAML 48 importing 49 !ABAP_DATA type DATA 50 !NAME type STRING optional 51 !UPCASE type XFELD optional 52 !Y_LEVEL type I default 0 53 !S_INDEX type I default 0 54 !FIRST_ROW type XFELD optional 55 !DONT_INDENT type XFELD optional 56 returning 57 value(YAML_STRING) type STRING 58 exceptions 59 ERROR_IN_DATA_DESCRIPTION . 60 class-methods BUILD_PARAMS 61 importing 62 !FUNCTION_NAME type RS38L_FNAM 63 exporting 64 !PARAMTAB type ABAP_FUNC_PARMBIND_TAB 65 !EXCEPTAB type ABAP_FUNC_EXCPBIND_TAB 66 !PARAMS type ANY 67 exceptions 68 INVALID_FUNCTION 69 UNSUPPORTED_PARAM_TYPE . 70 class-methods JSON2ABAP 71 importing 72 !JSON_STRING type STRING optional 73 !VAR_NAME type STRING optional 74 !PROPERTY_PATH type STRING default 'json_obj' 75 exporting 76 value(PROPERTY_TABLE) type JS_PROPERTY_TAB 77 changing 78 !JS_OBJECT type ref to CL_JAVA_SCRIPT optional 79 value(ABAP_DATA) type ANY optional 80 raising 81 ZCX_JSON . 82 class-methods JSON_DESERIALIZE 83 importing 84 !JSON type STRING 85 changing 86 !PARAMTAB type ABAP_FUNC_PARMBIND_TAB 87 raising 88 ZCX_JSON . 89 methods NOTES 90 returning 91 value(TEXT) type STRING . 92 class-methods SERIALIZE_JSON 93 importing 94 !PARAMTAB type ABAP_FUNC_PARMBIND_TAB 95 !PARAMS type ANY optional 96 !EXCEPTAB type ABAP_FUNC_EXCPBIND_TAB optional 97 !SHOW_IMPP type ABAP_BOOL optional 98 !JSONP type STRING optional 99 !LOWERCASE type ABAP_BOOL default ABAP_TRUE 100 !CAMELCASE type ABAP_BOOL default ABAP_FALSE 101 !CAMELCASE_NAMES type STRINGTAB optional 102 exporting 103 !O_STRING type STRING . 104 class-methods SERIALIZE_PERL 105 importing 106 !PARAMTAB type ABAP_FUNC_PARMBIND_TAB 107 !PARAMS type ANY optional 108 !EXCEPTAB type ABAP_FUNC_EXCPBIND_TAB optional 109 !SHOW_IMPP type ABAP_BOOL optional 110 !JSONP type STRING optional 111 !LOWERCASE type ABAP_BOOL default ABAP_FALSE 112 !FUNCNAME type RS38L_FNAM 113 exporting 114 !PERL_STRING type STRING . 115 class-methods SERIALIZE_XML 116 importing 117 !PARAMTAB type ABAP_FUNC_PARMBIND_TAB 118 !PARAMS type ANY optional 119 !EXCEPTAB type ABAP_FUNC_EXCPBIND_TAB optional 120 !SHOW_IMPP type ABAP_BOOL optional 121 !JSONP type STRING optional 122 !FUNCNAME type RS38L_FNAM 123 !LOWERCASE type ABAP_BOOL default ABAP_FALSE 124 !FORMAT type STRING optional 125 exporting 126 !O_STRING type STRING . 127 class-methods SERIALIZE_YAML 128 importing 129 !PARAMTAB type ABAP_FUNC_PARMBIND_TAB 130 !PARAMS type ANY optional 131 !EXCEPTAB type ABAP_FUNC_EXCPBIND_TAB optional 132 !SHOW_IMPP type ABAP_BOOL optional 133 !JSONP type STRING optional 134 !LOWERCASE type ABAP_BOOL default ABAP_FALSE 135 exporting 136 !YAML_STRING type STRING . 137 class-methods DESERIALIZE_ID 138 importing 139 !JSON type STRING 140 changing 141 !PARAMTAB type ABAP_FUNC_PARMBIND_TAB 142 raising 143 ZCX_JSON . 144 class-methods SERIALIZE_ID 145 importing 146 !PARAMTAB type ABAP_FUNC_PARMBIND_TAB 147 !PARAMS type ANY optional 148 !EXCEPTAB type ABAP_FUNC_EXCPBIND_TAB optional 149 !SHOW_IMPP type ABAP_BOOL optional 150 !JSONP type STRING optional 151 !LOWERCASE type ABAP_BOOL default ABAP_FALSE 152 !FORMAT type STRING default 'JSON' 153 !FUNCNAME type RS38L_FNAM optional 154 !CAMELCASE type ABAP_BOOL default ABAP_FALSE 155 exporting 156 !O_STRING type STRING 157 raising 158 ZCX_JSON . 159 protected section. 160 *"* protected components of class ZCL_JSON_HANDLER 161 *"* do not include other source files here!!! 162 private section. 163 *"* private components of class ZCL_JSON_HANDLER 164 *"* do not include other source files here!!! 165 ENDCLASS. 166 167 168 169 CLASS ZCL_JSON_HANDLER IMPLEMENTATION. 170 171 172 *' 2181 2182 '---------------------------------------------------------------------------------------+ 173 * | Static Public Method ZCL_JSON_HANDLER=>ABAP2JSON 174 * +-------------------------------------------------------------------------------------------------+ 175 * | [--->] ABAP_DATA TYPE DATA 176 * | [--->] NAME TYPE STRING(optional) 177 * | [--->] UPCASE TYPE XFELD(optional) 178 * | [--->] CAMELCASE TYPE XFELD(optional) 179 * | [--->] CAMELCASE_NAMES TYPE STRINGTAB(optional) 180 * | [<-()] JSON_STRING TYPE STRING 181 * | [EXC!] ERROR_IN_DATA_DESCRIPTION 182 * +-------------------------------------------------------------------------------------- 183 method abap2json. 184 */**********************************************/* 185 */ This method takes any ABAP data variable and /* 186 */ returns a string representing its value in /* 187 */ JSON format. /* 188 */ ABAP references are always de-referenced and /* 189 */ treated as normal variables. /* 190 */**********************************************/* 191 192 type-pools: abap. 193 194 constants: 195 c_comma type c value ',', 196 c_colon type c value ':', 197 c_quote type c value '"'. 198 199 data: 200 dont_quote type xfeld, 201 json_fragments type table of string, 202 rec_json_string type string, 203 l_type type c, 204 s_type type c, 205 l_comps type i, 206 l_lines type i, 207 l_index type i, 208 l_value type string, 209 l_name type string, 210 l_strudescr type ref to cl_abap_structdescr. 211 212 field-symbols: 213type any, 214 type any table, 215 type any table, 216 type any, 217 type abap_compdescr. 218 219 data my_camelcase type xfeld. 220 my_camelcase = camelcase. 221 222 define get_scalar_value. 223 " &1 : assigned var 224 " &2 : abap data 225 " &3 : abap type 226 &1 = &2. 227 **************************************************** 228 * Adapt some basic ABAP types (pending inclusion of all basic abap types?) 229 * Feel free to customize this for your needs 230 case &3. 231 * 1. ABAP numeric types 232 when 'I'. " Integer 233 condense &1. 234 if sign( &1 ) < 0. 235 shift &1 by 1 places right circular. 236 endif. 237 dont_quote = 'X'. 238 239 when 'F'. " Float 240 condense &1. 241 dont_quote = 'X'. 242 243 when 'P'. " Packed number (used in quantities or currency, for example) 244 condense &1. 245 if sign( &1 ) < 0. 246 shift &1 by 1 places right circular. 247 endif. 248 dont_quote = 'X'. 249 250 when 'X'. " Hexadecimal 251 condense &1. 252 concatenate '0x' &1 into &1. 253 * dont_quote = 'X'. 254 * "Quote it, as JSON doesn't support Hex or Octal as native types. 255 256 * 2. ABAP char types 257 when 'D'. " Date type 258 CONCATENATE &1(4) '-' &1+4(2) '-' &1+6(2) INTO &1. 259 260 when 'T'. " Time representation 261 CONCATENATE &1(2) ':' &1+2(2) ':' &1+4(2) INTO &1. 262 263 when 'N'. " Numeric text field 264 * condense &1. 265 266 when 'C' or 'g'. " Char sequences and Strings 267 * Put safe chars 268 replace all occurrences of '\' in &1 with '\\' . 269 replace all occurrences of '"' in &1 with '\"' . 270 replace all occurrences of cl_abap_char_utilities=>cr_lf in &1 with '\r\n' . 271 replace all occurrences of cl_abap_char_utilities=>newline in &1 with '\n' . 272 replace all occurrences of cl_abap_char_utilities=>horizontal_tab in &1 with '\t' . 273 replace all occurrences of cl_abap_char_utilities=>backspace in &1 with '\b' . 274 replace all occurrences of cl_abap_char_utilities=>form_feed in &1 with '\f' . 275 276 when 'y'. " XSTRING 277 * Put the XSTRING in Base64 278 &1 = cl_http_utility=>ENCODE_X_BASE64( &2 ). 279 280 when others. 281 * Don't hesitate to add and modify scalar abap types to suit your taste. 282 283 endcase. 284 ** End of scalar data preparing. 285 286 * Enclose value in quotes (or not) 287 if dont_quote ne 'X'. 288 concatenate c_quote &1 c_quote into &1. 289 endif. 290 291 clear dont_quote. 292 293 end-of-definition. 294 295 296 *************************************************** 297 * Prepare field names, JSON does quote names!! * 298 * You must be strict in what you produce. * 299 *************************************************** 300 if name is not initial. 301 concatenate c_quote name c_quote c_colon into rec_json_string. 302 append rec_json_string to json_fragments. 303 clear rec_json_string. 304 endif. 305 306 ** 307 * Get ABAP data type 308 describe field abap_data type l_type components l_comps. 309 310 *************************************************** 311 * Get rid of data references 312 *************************************************** 313 if l_type eq cl_abap_typedescr=>typekind_dref. 314 assign abap_data->* to . 315 if sy-subrc ne 0. 316 append '{}' to json_fragments. 317 concatenate lines of json_fragments into json_string. 318 exit. 319 endif. 320 else. 321 assign abap_data to . 322 endif. 323 324 * Get ABAP data type again and start 325 describe field type l_type components l_comps. 326 327 *************************************************** 328 * Tables 329 *************************************************** 330 if l_type eq cl_abap_typedescr=>typekind_table. 331 * '[' JSON table opening bracket 332 append '[' to json_fragments. 333 assign to . 334 l_lines = lines( ). 335 loop at assigning . 336 add 1 to l_index. 337 *> Recursive call for each table row: 338 rec_json_string = abap2json( abap_data = upcase = upcase camelcase = my_camelcase camelcase_names = camelcase_names ). 339 append rec_json_string to json_fragments. 340 clear rec_json_string. 341 if l_index < l_lines. 342 append c_comma to json_fragments. 343 endif. 344 endloop. 345 append ']' to json_fragments. 346 * ']' JSON table closing bracket 347 348 349 *************************************************** 350 * Structures 351 *************************************************** 352 else. 353 if l_comps is not initial. 354 * '{' JSON object opening curly brace 355 append '{' to json_fragments. 356 l_strudescr ?= cl_abap_typedescr=>describe_by_data( ). 357 loop at l_strudescr->components assigning . 358 l_index = sy-tabix . 359 assign component -name of structure to . 360 l_name = -name. 361 ** ABAP names are usually in caps, set upcase to avoid the conversion to lower case. 362 if upcase ne 'X'. 363 " translate l_name to lower case. 364 l_name = to_lower( l_name ). 365 endif. 366 if camelcase eq 'X'. 367 l_name = to_mixed( val = l_name case = 'a' ). 368 else. 369 read table camelcase_names from l_name transporting no fields. 370 if sy-subrc eq 0. 371 l_name = to_mixed( val = l_name case = 'a' ). 372 my_camelcase = 'X'. 373 else. 374 my_camelcase = abap_false. 375 endif. 376 endif. 377 describe field type s_type. 378 if s_type eq cl_abap_typedescr=>typekind_table or s_type eq cl_abap_typedescr=>typekind_dref or 379 s_type eq cl_abap_typedescr=>typekind_struct1 or s_type eq cl_abap_typedescr=>typekind_struct2. 380 *> Recursive call for non-scalars: 381 rec_json_string = abap2json( abap_data = name = l_name upcase = upcase camelcase = my_camelcase camelcase_names = camelcase_names ). 382 else. 383 if s_type eq cl_abap_typedescr=>typekind_oref or s_type eq cl_abap_typedescr=>typekind_iref. 384 rec_json_string = '"REF UNSUPPORTED"'. 385 else. 386 get_scalar_value rec_json_string s_type. 387 endif. 388 concatenate c_quote l_name c_quote c_colon rec_json_string into rec_json_string. 389 endif. 390 append rec_json_string to json_fragments. 391 clear rec_json_string. clear l_name. 392 if l_index < l_comps. 393 append c_comma to json_fragments. 394 endif. 395 endloop. 396 append '}' to json_fragments. 397 * '}' JSON object closing curly brace 398 399 400 **************************************************** 401 * - Scalars - * 402 **************************************************** 403 else. 404 get_scalar_value l_value l_type. 405 append l_value to json_fragments. 406 407 endif. 408 * End of structure/scalar IF block. 409 *********************************** 410 411 endif. 412 * End of main IF block. 413 ********************** 414 415 * Use a loop in older releases that don't support concatenate lines. 416 concatenate lines of json_fragments into json_string. 417 418 endmethod. 419 420 421 * ---------------------------------------------------------------------------------------+ 422 * | Static Public Method ZCL_JSON_HANDLER=>ABAP2PERL 423 * +-------------------------------------------------------------------------------------------------+ 424 * | [--->] ABAP_DATA TYPE DATA 425 * | [--->] NAME TYPE STRING(optional) 426 * | [--->] UPCASE TYPE XFELD(optional) 427 * | [<-()] PERL_STRING TYPE STRING 428 * | [EXC!] ERROR_IN_DATA_DESCRIPTION 429 * +-------------------------------------------------------------------------------------- 430 method ABAP2PERL. 431 */**********************************************/* 432 */ This method takes any ABAP data variable and /* 433 */ returns a string representing its value in /* 434 */ Perl Data::Dumper format, ready to be evaled /* 435 */ in a Perl program. /* 436 */**********************************************/* 437 438 type-pools: abap. 439 440 constants: 441 c_comma type c value ',', 442 c_colon type c value ':', 443 c_quote type c value ''''. 444 445 data: 446 perl_hash_assign type string, 447 dont_quote type xfeld, 448 perl_fragments type table of string, 449 rec_perl_string type string, 450 l_type type c, 451 s_type type c, 452 l_comps type i, 453 l_lines type i, 454 l_index type i, 455 l_value type string, 456 l_name type string, 457 l_typedescr type ref to cl_abap_structdescr. 458 459 field-symbols: 460type any, 461 type any table, 462 type any table, 463 type any, 464 type abap_compdescr. 465 466 concatenate space '=>' space into perl_hash_assign respecting blanks. 467 468 define get_scalar_value. 469 " &1 : assigned var 470 " &2 : abap data 471 " &3 : abap type 472 &1 = &2. 473 **************************************************** 474 * Adapt some basic ABAP types (pending inclusion of all basic abap types?) 475 * Feel free to customize this for your needs 476 case &3. 477 * 1. ABAP numeric types 478 when 'I'. " Integer 479 condense &1. 480 if sign( &1 ) < 0. 481 shift &1 by 1 places right circular. 482 endif. 483 dont_quote = 'X'. 484 485 when 'F'. " Float 486 condense &1. 487 dont_quote = 'X'. 488 489 when 'P'. " Packed number (used in quantities, for example) 490 condense &1. 491 if sign( &1 ) < 0. 492 shift &1 by 1 places right circular. 493 endif. 494 dont_quote = 'X'. 495 496 when 'X'. " Hexadecimal 497 condense &1. 498 concatenate '0x' &1 into &1. 499 dont_quote = 'X'. 500 501 * 2. ABAP char types 502 when 'D'. " Date type 503 CONCATENATE &1(4) '-' &1+4(2) '-' &1+6(2) INTO &1. 504 505 when 'T'. " Time representation 506 CONCATENATE &1(2) ':' &1+2(2) ':' &1+4(2) INTO &1. 507 508 when 'N'. " Numeric text field 509 * condense &1. 510 511 when 'C' or 'g'. " Char sequences and Strings 512 * Put safe chars 513 replace all occurrences of '''' in &1 with '\''' . 514 515 when 'y'. " XSTRING 516 * Put the XSTRING in Base64 517 &1 = cl_http_utility=>ENCODE_X_BASE64( &2 ). 518 519 when others. 520 * Don't hesitate to add and modify abap types to suit your taste. 521 522 endcase. 523 ** End of scalar data preparing. 524 525 * Enclose value in quotes (or not) 526 if dont_quote ne 'X'. 527 concatenate c_quote &1 c_quote into &1. 528 endif. 529 clear dont_quote. 530 531 end-of-definition. 532 533 534 535 *************************************************** 536 * Prepare field names, we use single quotes. * 537 * You must be strict in what you produce. * 538 *************************************************** 539 if name is not initial. 540 concatenate c_quote name c_quote perl_hash_assign into rec_perl_string respecting blanks. 541 append rec_perl_string to perl_fragments. 542 clear rec_perl_string. 543 endif. 544 545 ** 546 * Get ABAP data type 547 describe field abap_data type l_type components l_comps. 548 549 *************************************************** 550 * Get rid of data references 551 *************************************************** 552 if l_type eq cl_abap_typedescr=>typekind_dref. 553 assign abap_data->* to . 554 if sy-subrc ne 0. 555 append '{}' to perl_fragments. 556 concatenate lines of perl_fragments into perl_string. 557 exit. 558 endif. 559 else. 560 assign abap_data to . 561 endif. 562 563 564 * Get ABAP data type again and start 565 describe field type l_type components l_comps. 566 567 *************************************************** 568 * Tables 569 *************************************************** 570 if l_type eq cl_abap_typedescr=>typekind_table. 571 * '[' Table opening bracket 572 append '[' to perl_fragments. 573 assign to . 574 l_lines = lines( ). 575 loop at assigning . 576 add 1 to l_index. 577 *> Recursive call here 578 rec_perl_string = abap2perl( abap_data = upcase = upcase ). 579 append rec_perl_string to perl_fragments. 580 clear rec_perl_string. 581 if l_index < l_lines. 582 append c_comma to perl_fragments. 583 endif. 584 endloop. 585 append ']' to perl_fragments. 586 * ']' Table closing bracket 587 588 589 *************************************************** 590 * Structures 591 *************************************************** 592 else . 593 if l_comps is not initial. 594 * '{' Object opening curly brace 595 append '{' to perl_fragments . 596 l_typedescr ?= cl_abap_typedescr=>describe_by_data( ) . 597 loop at l_typedescr->components assigning . 598 l_index = sy-tabix . 599 assign component -name of structure to . 600 l_name = -name. 601 ** ABAP names are usually in caps, set upcase to avoid the conversion to lower case. 602 if upcase ne 'X'. 603 translate l_name to lower case. 604 endif. 605 describe field type s_type. 606 if s_type eq cl_abap_typedescr=>typekind_table or s_type eq cl_abap_typedescr=>typekind_dref or 607 s_type eq cl_abap_typedescr=>typekind_struct1 or s_type eq cl_abap_typedescr=>typekind_struct2. 608 *> Recursive call for non-scalars: 609 rec_perl_string = abap2perl( abap_data = name = l_name upcase = upcase ). 610 else. 611 if s_type eq cl_abap_typedescr=>TYPEKIND_OREF or s_type eq cl_abap_typedescr=>TYPEKIND_IREF. 612 rec_perl_string = '"REF UNSUPPORTED"'. 613 else. 614 get_scalar_value rec_perl_string s_type. 615 endif. 616 concatenate c_quote l_name c_quote perl_hash_assign rec_perl_string into rec_perl_string. 617 endif. 618 619 append rec_perl_string to perl_fragments. 620 clear rec_perl_string. 621 if l_index < l_comps. 622 append c_comma to perl_fragments. 623 endif. 624 endloop. 625 append '}' to perl_fragments. 626 * '}' Object closing curly brace 627 628 629 **************************************************** 630 * - Scalars - * 631 **************************************************** 632 else. 633 634 get_scalar_value l_value l_type. 635 append l_value to perl_fragments. 636 637 endif. 638 * End of structure/scalar IF block. 639 *********************************** 640 641 642 endif. 643 * End of main IF block. 644 ********************** 645 646 647 * Use a loop in older releases that don't support concatenate lines. 648 concatenate lines of perl_fragments into perl_string. 649 650 endmethod. 651 652 653 * ---------------------------------------------------------------------------------------+ 654 * | Static Public Method ZCL_JSON_HANDLER=>ABAP2XML 655 * +-------------------------------------------------------------------------------------------------+ 656 * | [--->] ABAP_DATA TYPE DATA 657 * | [--->] NAME TYPE STRING(optional) 658 * | [--->] WITH_XML_HEADER TYPE ABAP_BOOL (default =ABAP_FALSE) 659 * | [--->] UPCASE TYPE XFELD(optional) 660 * | [--->] NAME_ATR TYPE STRING(optional) 661 * | [<-()] XML_STRING TYPE STRING 662 * +-------------------------------------------------------------------------------------- 663 method ABAP2XML. 664 * 665 */ Look at method serialize_id for a new way of doing XML. 666 667 type-pools: abap. 668 669 constants: 670 xml_head type string value '<?xml version="1.0" encoding="utf-8"?>', 671 item_atr type string value 'idx="#"'. 672 673 data: 674 xml_fragments type table of string, 675 rec_xml_string type string, 676 l_type type c, 677 s_type type c, 678 l_comps type i, 679 l_value type string, 680 t_string type string, 681 l_item_atr type string, 682 l_item_str type string, 683 l_name type string, 684 l_idx type string, 685 l_typedescr type ref to cl_abap_structdescr, 686 l_linedescr type ref to cl_abap_datadescr, 687 l_tabledescr type ref to cl_abap_tabledescr. 688 689 field-symbols: 690type any, 691 type any table, 692 type any table, 693 type any, 694 type abap_compdescr. 695 696 define get_scalar_value. 697 " &1 : assigned var 698 " &2 : abap data 699 " &3 : abap type 700 &1 = &2. 701 **************************************************** 702 * Adapt some basic ABAP types (pending inclusion of all basic abap types?) 703 * Feel free to customize this for your needs 704 case &3. 705 * 1. ABAP numeric types 706 when 'I'. " Integer 707 condense &1. 708 if sign( &1 ) < 0. 709 shift &1 by 1 places right circular. 710 endif. 711 712 when 'F'. " Float 713 condense &1. 714 715 when 'P'. " Packed number (used in quantities, for example) 716 condense &1. 717 if sign( &1 ) < 0. 718 shift &1 by 1 places right circular. 719 endif. 720 721 when 'X'. " Hexadecimal 722 condense &1. 723 concatenate '0x' &1 into &1. 724 725 * 2. ABAP char types 726 when 'D'. " Date type 727 CONCATENATE &1(4) '-' &1+4(2) '-' &1+6(2) INTO &1. 728 729 when 'T'. " Time representation 730 CONCATENATE &1(2) ':' &1+2(2) ':' &1+4(2) INTO &1. 731 732 when 'N'. " Numeric text field 733 * condense &1. 734 735 when 'C' or 'g'. " Char sequences and Strings 736 * Put safe chars 737 t_string = &2. 738 &1 = cl_http_utility=>escape_html( t_string ). 739 740 when 'y'. " XSTRING 741 * Put the XSTRING in Base64 742 &1 = cl_http_utility=>ENCODE_X_BASE64( &2 ). 743 744 when others. 745 * Don't hesitate to add and modify abap types to suit your taste. 746 747 endcase. 748 ** End of scalar data preparing. 749 750 end-of-definition. 751 752 753 754 ******************************* 755 * Put XML header if requested * 756 ******************************* 757 if with_xml_header eq abap_true. 758 append xml_head to xml_fragments. 759 endif. 760 761 *************************************************** 762 * Open XML tag * 763 * < > * 764 *************************************************** 765 if name is not initial. 766 l_name = name. 767 if name_atr is not initial. 768 concatenate name name_atr into l_name separated by space. 769 endif. 770 concatenate '<' l_name '>' into rec_xml_string. 771 append rec_xml_string to xml_fragments. 772 clear rec_xml_string. 773 endif. 774 775 ** 776 * Get ABAP data type 777 describe field abap_data type l_type components l_comps . 778 779 *************************************************** 780 * Get rid of data references 781 *************************************************** 782 if l_type eq cl_abap_typedescr=>typekind_dref. 783 assign abap_data->* to . 784 if sy-subrc ne 0. 785 if name is not initial. 786 concatenate '<' name '/>' into xml_string. 787 else. 788 clear xml_string. 789 endif. 790 exit. 791 endif. 792 else. 793 assign abap_data to . 794 endif. 795 796 797 * Get ABAP data type again and start 798 describe field type l_type components l_comps. 799 800 801 *************************************************** 802 * Tables 803 *************************************************** 804 if l_type eq cl_abap_typedescr=>typekind_table. 805 l_tabledescr ?= cl_abap_typedescr=>describe_by_data( ). 806 l_linedescr = l_tabledescr->get_table_line_type( ). 807 l_item_str = l_linedescr->get_relative_name( ). 808 assign to . 809 loop at assigning . 810 l_idx = sy-tabix. 811 condense l_idx. 812 l_item_atr = item_atr. 813 replace '#' in l_item_atr with l_idx. 814 if upcase ne 'X'. 815 translate l_item_str to lower case. 816 endif. 817 *> Recursive call for line items here: 818 rec_xml_string = abap2xml( abap_data = upcase = upcase name = l_item_str name_atr = l_item_atr ). 819 append rec_xml_string to xml_fragments. 820 clear rec_xml_string. 821 endloop. 822 823 824 *************************************************** 825 * Structures 826 *************************************************** 827 else . 828 if l_comps is not initial. 829 l_typedescr ?= cl_abap_typedescr=>describe_by_data( ). 830 loop at l_typedescr->components assigning . 831 assign component -name of structure to . 832 l_name = -name. " l_value justs holds the name here. 833 ** ABAP names are usually in caps, set upcase to avoid the conversion to lower case. 834 if upcase ne 'X'. 835 translate l_name to lower case. 836 endif. 837 describe field type s_type. 838 if s_type eq cl_abap_typedescr=>typekind_table or s_type eq cl_abap_typedescr=>typekind_dref or 839 s_type eq cl_abap_typedescr=>typekind_struct1 or s_type eq cl_abap_typedescr=>typekind_struct2. 840 *> Recursive call for non-scalars: 841 rec_xml_string = abap2xml( abap_data = name = l_name upcase = upcase ). 842 else. 843 if s_type eq cl_abap_typedescr=>TYPEKIND_OREF or s_type eq cl_abap_typedescr=>TYPEKIND_IREF. 844 rec_xml_string = 'REF UNSUPPORTED'. 845 else. 846 get_scalar_value rec_xml_string s_type. 847 endif. 848 concatenate '<' l_name '>' rec_xml_string '' l_name '>' into rec_xml_string. 849 endif. 850 append rec_xml_string to xml_fragments. 851 clear rec_xml_string. 852 endloop. 853 854 855 856 **************************************************** 857 * - Scalars - * 858 **************************************************** 859 else. 860 861 get_scalar_value l_value l_type. 862 append l_value to xml_fragments. 863 864 endif. 865 * End of structure/scalar IF block. 866 *********************************** 867 868 869 endif. 870 * End of main IF block. 871 ********************** 872 873 874 ***************** 875 * Close XML tag * 876 ***************** 877 if name is not initial. 878 concatenate '' name '>' into rec_xml_string. 879 append rec_xml_string to xml_fragments. 880 clear rec_xml_string. 881 endif. 882 883 * Use a loop in older releases that don't support concatenate lines. 884 concatenate lines of xml_fragments into xml_string. 885 886 endmethod. 887 888 889 * ---------------------------------------------------------------------------------------+ 890 * | Static Public Method ZCL_JSON_HANDLER=>ABAP2YAML 891 * +-------------------------------------------------------------------------------------------------+ 892 * | [--->] ABAP_DATA TYPE DATA 893 * | [--->] NAME TYPE STRING(optional) 894 * | [--->] UPCASE TYPE XFELD(optional) 895 * | [--->] Y_LEVEL TYPE I (default =0) 896 * | [--->] S_INDEX TYPE I (default =0) 897 * | [--->] FIRST_ROW TYPE XFELD(optional) 898 * | [--->] DONT_INDENT TYPE XFELD(optional) 899 * | [<-()] YAML_STRING TYPE STRING 900 * | [EXC!] ERROR_IN_DATA_DESCRIPTION 901 * +-------------------------------------------------------------------------------------- 902 method ABAP2YAML. 903 ********************* 904 * ABAP goes to YAML * 905 ********************* 906 907 type-pools: abap. 908 909 constants: 910 c_comma type c value ',', 911 c_space type c value ' ', 912 c_colon type c value ':', 913 c_quote type c value '"', 914 c_squot type c value '''', 915 c_colo2(2) type c value ': ', 916 c_indt2 type i value 2, 917 c_hyph type c value '-'. 918 919 data: 920 ly_level type i, 921 l_dont_indent type xfeld, 922 dec_level type i value 0, 923 dont_quote type xfeld, 924 yaml_fragments type table of string, 925 rec_yaml_string type string, 926 l_type type c , 927 l_comps type i , 928 l_lines type i , 929 l_index type i , 930 l_value type string, 931 l_name type string. 932 field-symbols: 933type any, 934 type any table, 935 type any table, 936 type any. 937 data l_typedescr type ref to cl_abap_structdescr . 938 field-symbols type abap_compdescr . 939 940 ly_level = y_level. 941 942 ** 943 * Get ABAP data type 944 describe field abap_data type l_type components l_comps . 945 946 *************************************************** 947 * First of all, get rid of data references 948 *************************************************** 949 if l_type eq cl_abap_typedescr=>typekind_dref. 950 assign abap_data->* to . 951 if sy-subrc ne 0. 952 yaml_string = space. " pasamos de poner nada si falla... 953 exit. 954 endif. 955 else. 956 assign abap_data to . 957 endif. 958 959 960 * Get ABAP data type again and start 961 describe field type l_type components l_comps. 962 963 *************************************************** 964 * Prepare field names, YAML does not quote names * 965 *************************************************** 966 * Put hyphens... 967 if name is initial and y_level gt 0. 968 concatenate c_hyph space into rec_yaml_string respecting blanks. 969 l_dont_indent = 'X'. 970 endif. 971 972 if name is not initial. 973 concatenate name c_colon c_space into rec_yaml_string respecting blanks. 974 endif. 975 976 * do indent 977 if dont_indent ne 'X'. 978 do ly_level times. 979 shift rec_yaml_string right by c_indt2 places. 980 enddo. 981 endif. 982 983 append rec_yaml_string to yaml_fragments. 984 clear rec_yaml_string. 985 986 987 988 989 *************************************************** 990 * Tables 991 *************************************************** 992 if l_type eq cl_abap_typedescr=>TYPEKIND_TABLE. 993 assign to . 994 l_lines = lines( ). 995 clear l_index. 996 if l_lines eq 0. 997 move '[]' to rec_yaml_string. 998 append rec_yaml_string to yaml_fragments. 999 clear rec_yaml_string. 1000 append xnl to yaml_fragments. 1001 else. 1002 if name is not initial. 1003 append xnl to yaml_fragments. 1004 endif. 1005 add 1 to ly_level. 1006 loop at assigning . 1007 add 1 to l_index. 1008 *> Recursive call here 1009 rec_yaml_string = abap2yaml( abap_data = upcase = upcase y_level = ly_level s_index = l_index ). 1010 append rec_yaml_string to yaml_fragments. 1011 clear rec_yaml_string. 1012 endloop. 1013 endif. 1014 * YAML table ends * 1015 ******************* 1016 1017 1018 *************************************************** 1019 * Structures 1020 *************************************************** 1021 else . 1022 if l_comps is not initial. 1023 if name is not initial. 1024 append xnl to yaml_fragments. 1025 endif. 1026 add 1 to ly_level. 1027 * Loop for structure elements 1028 l_typedescr ?= cl_abap_typedescr=>describe_by_data( ) . 1029 clear l_index. 1030 loop at l_typedescr->components assigning . 1031 add 1 to l_index. 1032 assign component -name of structure to . 1033 l_name = -name. 1034 ** ABAP names are usually in caps, set upcase to avoid the conversion to lower case. 1035 if upcase ne 'X'. 1036 translate l_name to lower case. 1037 endif. 1038 *> Recursive call here 1039 rec_yaml_string = abap2yaml( abap_data = name = l_name upcase = upcase y_level = ly_level s_index = l_index dont_indent = l_dont_indent ). 1040 clear l_dont_indent. " it is only used once 1041 append rec_yaml_string to yaml_fragments. 1042 clear rec_yaml_string. 1043 endloop. 1044 1045 * YAML structure ends * 1046 *********************** 1047 1048 1049 *************************************************** 1050 * Scalars and others... 1051 *************************************************** 1052 else. 1053 if l_type eq cl_abap_typedescr=>TYPEKIND_OREF or l_type eq cl_abap_typedescr=>TYPEKIND_IREF. 1054 l_value = 'REF UNSUPPORTED'. 1055 else. 1056 l_value = . 1057 endif. 1058 1059 * Adapt some basic ABAP types (pending inclusion of all basic abap types) 1060 * Feel free to customize this for your needs 1061 case l_type. 1062 * 1. ABAP numeric types 1063 when 'I'. " Integer 1064 condense l_value. 1065 if sign( l_value ) < 0. 1066 shift l_value by 1 places right circular. 1067 endif. 1068 dont_quote = 'X'. 1069 1070 when 'F'. " Float 1071 condense l_value. 1072 dont_quote = 'X'. 1073 1074 when 'P'. " Packed number (used in quantities, for example) 1075 condense l_value. 1076 if sign( l_value ) < 0. 1077 shift l_value by 1 places right circular. 1078 endif. 1079 dont_quote = 'X'. 1080 1081 when 'X'. " Hexadecimal 1082 condense l_value. 1083 concatenate '0x' l_value into l_value. 1084 dont_quote = 'X'. 1085 1086 * 2. ABAP char types 1087 when 'D'. " Date type 1088 CONCATENATE l_value(4) '-' l_value+4(2) '-' l_value+6(2) INTO l_value. 1089 1090 when 'T'. " Time representation 1091 CONCATENATE l_value(2) ':' l_value+2(2) ':' l_value+4(2) INTO l_value. 1092 1093 when 'N'. " Numeric text field 1094 * condense l_value. 1095 1096 when 'C' or 'g'. " Chars and Strings 1097 * Put safe chars 1098 replace all occurrences of '\' in l_value with '\\' . 1099 replace all occurrences of '"' in l_value with '\"' . 1100 replace all occurrences of cl_abap_char_utilities=>cr_lf in l_value with '\r\n' . 1101 replace all occurrences of cl_abap_char_utilities=>newline in l_value with '\n' . 1102 replace all occurrences of cl_abap_char_utilities=>horizontal_tab in l_value with '\t' . 1103 replace all occurrences of cl_abap_char_utilities=>backspace in l_value with '\b' . 1104 replace all occurrences of cl_abap_char_utilities=>form_feed in l_value with '\f' . 1105 1106 when 'y'. " XSTRING 1107 * Put the XSTRING in Base64 1108 * l_value = cl_http_utility=>ENCODE_X_BASE64( ). 1109 l_value = 'XSTRING not supported in YAML yet!'. 1110 1111 when others. 1112 * Don't hesitate to add and modify abap types to suit your taste. 1113 1114 endcase. 1115 1116 * We use YAML scalars double quoted 1117 if dont_quote ne 'X'. 1118 concatenate c_quote l_value c_quote into l_value. 1119 else. 1120 clear dont_quote. 1121 endif. 1122 1123 append l_value to yaml_fragments. 1124 1125 append xnl to yaml_fragments. 1126 1127 endif. " is structure or scalar 1128 1129 endif. " main typekind sentence 1130 1131 1132 1133 * Use a loop in older releases that don't support concatenate lines. 1134 concatenate lines of yaml_fragments into yaml_string respecting blanks. 1135 1136 endmethod. 1137 1138 1139 *---------------------------------------------------------------------------------------+ 1140 * | Static Public Method ZCL_JSON_HANDLER=>BUILD_PARAMS 1141 * +-------------------------------------------------------------------------------------------------+ 1142 * | [--->] FUNCTION_NAME TYPE RS38L_FNAM 1143 * | [<---] PARAMTAB TYPE ABAP_FUNC_PARMBIND_TAB 1144 * | [<---] EXCEPTAB TYPE ABAP_FUNC_EXCPBIND_TAB 1145 * | [<---] PARAMS TYPE ANY 1146 * | [EXC!] INVALID_FUNCTION 1147 * | [EXC!] UNSUPPORTED_PARAM_TYPE 1148 * +-------------------------------------------------------------------------------------- 1149 method BUILD_PARAMS. 1150 1151 type-pools: ABAP. 1152 1153 data defval type RS38L_DEFO. 1154 data dataname type string. 1155 data waref type ref to data. 1156 1157 field-symbols: 1158type any, 1159 type any. 1160 1161 data len type i. 1162 data excnt type i value 1. 1163 1164 data paramline type line of ABAP_FUNC_PARMBIND_TAB. 1165 data exceptline type line of ABAP_FUNC_EXCPBIND_TAB. 1166 data t_params_p type table of RFC_FINT_P. 1167 data params_p type RFC_FINT_P. 1168 1169 define remove_enclosing_quotes. 1170 " Remove enclosing single quotes 1171 if &2 gt 1. 1172 subtract 1 from &2. 1173 if &1+&2 eq ''''. 1174 &1+&2 = space. 1175 endif. 1176 if &1(1) eq ''''. 1177 shift &1 left. 1178 endif. 1179 &2 = strlen( &1 ). 1180 endif. 1181 end-of-definition. 1182 1183 1184 * do we have the rfc name? 1185 call function 'RFC_GET_FUNCTION_INTERFACE_P' 1186 EXPORTING 1187 funcname = function_name 1188 language = 'E' "'D' "sy-langu 1189 TABLES 1190 params_p = t_params_p 1191 EXCEPTIONS 1192 fu_not_found = 1 1193 nametab_fault = 2 1194 others = 3. 1195 1196 if sy-subrc <> 0. 1197 raise INVALID_FUNCTION. 1198 endif. 1199 1200 1201 * Build params table 1202 loop at t_params_p into params_p. 1203 1204 unassign . 1205 unassign . 1206 clear paramline. 1207 1208 case params_p-paramclass. 1209 1210 when 'I' or 'E' or 'C'. 1211 1212 paramline-name = params_p-parameter. 1213 1214 if params_p-paramclass = 'E'. 1215 paramline-kind = ABAP_FUNC_IMPORTING. 1216 elseif params_p-paramclass = 'I'. 1217 paramline-kind = ABAP_FUNC_EXPORTING. 1218 else. 1219 paramline-kind = ABAP_FUNC_CHANGING. 1220 endif. 1221 1222 if params_p-fieldname is initial. 1223 dataname = params_p-tabname. 1224 else. 1225 concatenate params_p-tabname params_p-fieldname into 1226 dataname separated by '-'. 1227 endif. 1228 1229 * Assign default values 1230 defval = params_p-default. 1231 if dataname is initial. 1232 dataname = 'STRING'. " use a STRING for this cases (see CONVERT_DATE_TO_EXTERNAL). 1233 endif. 1234 create data waref type (dataname). 1235 assign waref->* to . 1236 len = strlen( defval ). 1237 remove_enclosing_quotes defval len. 1238 if defval = 'SPACE'. 1239 = space. 1240 elseif len > 3 and defval+0(3) = 'SY-'. 1241 assign (defval) to . 1242 = . 1243 unassign . 1244 else. 1245 if defval is not initial. 1246 = defval. 1247 endif. 1248 endif. 1249 unassign . 1250 paramline-value = waref. 1251 insert paramline into table paramtab. 1252 1253 when 'T'. 1254 paramline-name = params_p-parameter. 1255 paramline-kind = ABAP_FUNC_TABLES. 1256 if params_p-exid eq 'h'. 1257 create data waref type (params_p-tabname). 1258 else. 1259 create data waref type standard table of (params_p-tabname). 1260 endif. 1261 paramline-value = waref. 1262 insert paramline into table paramtab. 1263 1264 when 'X'. 1265 exceptline-name = params_p-parameter. 1266 exceptline-value = excnt. 1267 data messg type ref to data. 1268 create data messg type string. 1269 assign messg->* to . 1270 = params_p-paramtext. 1271 exceptline-message = messg. 1272 insert exceptline into table exceptab. 1273 add 1 to excnt. 1274 1275 when others. 1276 raise UNSUPPORTED_PARAM_TYPE. 1277 1278 endcase. 1279 1280 endloop. 1281 1282 1283 * add in the catch all exception 1284 exceptline-name = 'OTHERS'. 1285 exceptline-value = excnt. 1286 insert exceptline into table exceptab. 1287 1288 1289 * return 1290 params = t_params_p. 1291 1292 ********************************* 1293 ******* Remaining from 2006 ***** 1294 ******* end of build_params ***** 1295 ********************************* 1296 endmethod. 1297 1298 1299 * ---------------------------------------------------------------------------------------+ 1300 * | Static Public Method ZCL_JSON_HANDLER=>DESERIALIZE_ID 1301 * +-------------------------------------------------------------------------------------------------+ 1302 * | [--->] JSON TYPE STRING 1303 * | [<-->] PARAMTAB TYPE ABAP_FUNC_PARMBIND_TAB 1304 * | [!CX!] ZCX_JSON 1305 * +-------------------------------------------------------------------------------------- 1306 method DESERIALIZE_ID. 1307 */***********************************************************/* 1308 */ New method using the built-in transformation /* 1309 */ included in releases 7.02 and 7.03/7.31 (Kernelpatch 116) /* 1310 */***********************************************************/* 1311 1312 type-pools: ABAP. 1313 1314 ** Remember function parameter types 1315 **constants: 1316 ** abap_func_exporting type abap_func_parmbind-kind value 10, 1317 ** abap_func_importing type abap_func_parmbind-kind value 20, 1318 ** abap_func_tables type abap_func_parmbind-kind value 30, 1319 ** abap_func_changing type abap_func_parmbind-kind value 40. 1320 1321 data: 1322 rtab type ABAP_TRANS_RESBIND_TAB, 1323 rlin type abap_trans_resbind, 1324 oexcp type ref to cx_root, 1325 etext type string, 1326 json_xtext type xstring. 1327 1328 field-symbolstype abap_func_parmbind. 1329 1330 if json is initial. exit. endif. " exit method if there is nothing to parse 1331 1332 " build rtab table for transformation id 1333 1334 loop at paramtab assigning . 1335 if -kind eq abap_func_importing. "" va al revés, cuidado!!! 1336 continue. 1337 endif. 1338 rlin-name = -name. 1339 rlin-value = -value. 1340 append rlin to rtab. 1341 endloop. 1342 1343 " Convert input JSON variable names to uppercase 1344 1345 json_xtext = cl_abap_codepage=>convert_to( json ). 1346 data(reader) = cl_sxml_string_reader=>create( json_xtext ). 1347 data(writer) = cast if_sxml_writer( cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ) ). 1348 do. 1349 data(node) = reader->read_next_node( ). 1350 if node is initial. 1351 exit. 1352 endif. 1353 if node->type = if_sxml_node=>co_nt_element_open. 1354 data(attributes) = cast if_sxml_open_element( node )->get_attributes( ). 1355 loop at attributes assigning field-symbol( ). 1356 if ->qname-name = 'name'. 1357 ->set_value( 1358 to_upper( ->get_value( ) ) ). 1359 endif. 1360 endloop. 1361 endif. 1362 writer->write_node( node ). 1363 enddo. 1364 json_xtext = cast cl_sxml_string_writer( writer )->get_output( ) . 1365 1366 try. 1367 1368 CALL TRANSFORMATION id SOURCE XML json_xtext 1369 RESULT (rtab). 1370 1371 catch cx_root into oexcp. 1372 1373 etext = oexcp->if_message~get_text( ). 1374 RAISE EXCEPTION type zcx_json 1375 EXPORTING 1376 message = etext. 1377 1378 endtry. 1379 1380 endmethod. 1381 1382 1383 * ---------------------------------------------------------------------------------------+ 1384 * | Instance Public Method ZCL_JSON_HANDLER->IF_HTTP_EXTENSION~HANDLE_REQUEST 1385 * +-------------------------------------------------------------------------------------------------+ 1386 * | [--->] SERVER TYPE REF TO IF_HTTP_SERVER 1387 * +-------------------------------------------------------------------------------------- 1388 METHOD if_http_extension~handle_request. 1389 */*************************************************************************/ 1390 */ Assign this handler to a service in ICF. This allows any ABAP function */ 1391 */ module to be called directly by URL and exchange data in JSON format. */ 1392 */ -- 1393 */ This code is distributed under the terms of Apache License Version 2.0 */ 1394 */ (see http://www.apache.org/licenses/LICENSE-2.0.html) */ 1395 */ -- 1396 */ (C) César Martín*/ 1397 */ Many thanks to Juan Díez for his ideas, help, and support. */ 1398 */ -- 1399 */*************************************************************************/ 1400 */ If you want to use the SAP standard provided transformation for JSON */ 1401 */ and XML, uncomment the lines calling serialize_id and deserialize_id */ 1402 */*************************************************************************/ 1403 "INCLUDE zafl_macros."陈辉 增加日志 1404 TYPE-POOLS abap. 1405 1406 DATA: show_import_params TYPE abap_bool VALUE abap_false, 1407 upcase TYPE abap_bool VALUE abap_false, 1408 lowercase TYPE abap_bool VALUE abap_true, 1409 camelcase TYPE abap_bool VALUE abap_false, 1410 path_info TYPE string, 1411 p_info_tab TYPE TABLE OF string, 1412 format TYPE string, 1413 accept TYPE string, 1414 action TYPE string, 1415 request_method TYPE string, 1416 jsonp_callback TYPE string, 1417 i_content_type TYPE string, 1418 i_cdata TYPE string, 1419 o_cdata TYPE string, 1420 exceptheader TYPE string, 1421 etext TYPE string, 1422 etext2 TYPE string, 1423 str_item TYPE string, 1424 host TYPE string, 1425 port TYPE string, 1426 proto TYPE string, 1427 http_code TYPE i, 1428 http_status TYPE string, 1429 camelcase_names TYPE stringtab, 1430 1431 funcname TYPE rs38l_fnam, 1432 funcname2 TYPE string, 1433 dparam TYPE abap_parmname, 1434 t_params_p TYPE STANDARD TABLE OF rfc_fint_p, 1435 paramtab TYPE abap_func_parmbind_tab, 1436 exceptab TYPE abap_func_excpbind_tab, 1437 exception TYPE LINE OF abap_func_excpbind_tab, 1438 funcrc TYPE sy-subrc, 1439 oexcp TYPE REF TO cx_root, 1440 qs_nvp TYPE tihttpnvp, 1441 l_lines TYPE i, 1442 l_idx TYPE i. 1443 1444 TYPES:BEGIN OF ty_icf, 1445 request_method TYPE string, 1446 http_code TYPE i, 1447 http_status TYPE string, 1448 error_message TYPE string, 1449 location_header TYPE string, 1450 icf_url TYPE string, 1451 icf_service TYPE string, 1452 path_info TYPE string, 1453 delete_params TYPE stringtab, 1454 i_json_data TYPE string, 1455 qs_tab TYPE tihttpnvp, 1456 alt_response TYPE string, 1457 server TYPE REF TO if_http_server, 1458 camelcase_names TYPE stringtab, 1459 END OF ty_icf. 1460 FIELD-SYMBOLSTYPE ihttpnvp. 1461 FIELD-SYMBOLS TYPE abap_func_parmbind. 1462 FIELD-SYMBOLS TYPE string. 1463 FIELD-SYMBOLS TYPE i. 1464 FIELD-SYMBOLS TYPE ty_icf. "zicf_handler_data. 1465 1466 DEFINE http_error. 1467 " &1 http status code 1468 " &2 status text 1469 " &3 error message 1470 server->response->set_header_field( name = 'Content-Type' value = 'application/json' ). 1471 http_code = &1. 1472 server->response->set_status( code = http_code reason = &2 ). 1473 CONCATENATE '{"ERROR_CODE":"' &1 '","ERROR_MESSAGE":"' &3 '","INFO_LINK":"' me->my_url me->my_service '?action=notes"}' INTO etext. 1474 server->response->set_cdata( etext ). 1475 EXIT. 1476 END-OF-DEFINITION. 1477 1478 * Get Server Info: 1479 1480 server->get_location( IMPORTING host = host port = port out_protocol = proto ). 1481 CONCATENATE proto '://' host ':' port INTO me->my_url. 1482 1483 ** Get all client Info: 1484 *data clnt_hfields type TIHTTPNVP. 1485 *server->request->get_header_fields( changing fields = clnt_hfields ). 1486 1487 1488 * GET and POST and other methods are allowed. 1489 * Uncomment or extend this if you want alternative actions following 1490 * request methods, in order to define a REST style behaviour 1491 * or, better, check an alternative approach on a way to do that 1492 * inside the FM (search for _ICF_DATA below). 1493 * if request_method <> 'POST'. 1494 **** http_error 405 'Method not allowed' 'Method not allowed.'. 1495 * endif. 1496 1497 1498 * Get form and header fields 1499 me->my_service = server->request->get_header_field( name = '~script_name' ). 1500 request_method = server->request->get_header_field( name = '~request_method' ). 1501 i_content_type = server->request->get_header_field( name = 'content-type' ). 1502 show_import_params = server->request->get_form_field( 'show_import_params' ). 1503 action = server->request->get_form_field( 'action' ). 1504 jsonp_callback = server->request->get_form_field( 'callback' ). 1505 format = server->request->get_form_field( 'format' ). 1506 accept = server->request->get_header_field( name = 'Accept' ). 1507 1508 * the case with CASE and forgive the mess. 1509 * Now, it is lowercase by default. 1510 lowercase = server->request->get_form_field( 'lowercase' ). 1511 upcase = server->request->get_form_field( 'upcase' ). 1512 camelcase = server->request->get_form_field( 'camelcase' ). 1513 IF upcase NE abap_true. " only upcase matters. 1514 lowercase = abap_true. 1515 ENDIF. 1516 1517 1518 * Try "$" equivalents: 1519 IF format IS INITIAL. 1520 format = server->request->get_form_field( '$format' ). 1521 ENDIF. 1522 IF jsonp_callback IS INITIAL. 1523 jsonp_callback = server->request->get_form_field( '$callback' ). 1524 ENDIF. 1525 1526 * Get function name from PATH_INFO 1527 path_info = server->request->get_header_field( name = '~path_info' ). 1528 SPLIT path_info AT '/' INTO TABLE p_info_tab. 1529 READ TABLE p_info_tab INDEX 2 INTO funcname. 1530 READ TABLE p_info_tab INDEX 3 INTO funcname2. 1531 IF sy-subrc EQ 0. 1532 CONCATENATE '/' funcname '/' funcname2 INTO funcname. 1533 CONDENSE funcname. 1534 ENDIF. 1535 TRANSLATE funcname TO UPPER CASE. 1536 IF funcname IS INITIAL AND action IS INITIAL. 1537 http_error '404' 'Not Found' 'Empty request.' . 1538 ENDIF. 1539 1540 * Get the desired response format from "Accept" header (as in RFC 2616 sec 14.1) 1541 * See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html. Thanks Uwe!! 1542 IF accept IS NOT INITIAL AND format IS INITIAL. 1543 TRANSLATE accept TO LOWER CASE. 1544 IF accept CS '/json'. 1545 format = 'json'. 1546 ELSEIF accept CS '/yaml'. 1547 format = 'yaml'. 1548 ELSEIF accept CS '/xml'. 1549 format = 'xml'. 1550 ELSEIF accept CS '/perl'. 1551 format = 'perl'. 1552 ELSEIF accept CS '*/*'. 1553 CLEAR format. " for the moment, ignore quality levels in Accept, send default format (json). 1554 ELSE. 1555 http_error '406' 'Not Acceptable' 'The server cannot send a response which is acceptable according to the combined Accept field value'. 1556 ENDIF. 1557 ENDIF. 1558 1559 TRANSLATE format TO UPPER CASE. 1560 TRANSLATE action TO UPPER CASE. 1561 IF show_import_params IS NOT INITIAL. 1562 show_import_params = abap_true. 1563 ENDIF. 1564 1565 1566 *************************** 1567 * Do alternative actions... 1568 CASE action. 1569 WHEN 'NOTES'. 1570 server->response->set_header_field( name = 'Content-Type' value = 'text/html' ). 1571 server->response->set_status( code = 200 reason = 'OK' ). 1572 o_cdata = me->notes( ). 1573 server->response->set_cdata( o_cdata ). 1574 EXIT. 1575 * when 'TEST'. 1576 ****** TEST ***** 1577 * etext = me->test( i_cdata ). 1578 * http_error '200' 'Ok' etext. 1579 * exit. 1580 ****** Investigate further... ***** 1581 WHEN 'START_SESSION'. 1582 ** server->stateful = 1. 1583 server->set_session_stateful( stateful = server->co_enabled ). 1584 WHEN 'END_SESSION'. 1585 ** server->stateful = 0. 1586 server->set_session_stateful( stateful = server->co_disabled ). 1587 WHEN OTHERS. 1588 " just go on 1589 ENDCASE. 1590 1591 1592 1593 * Check Authorization. Create the relevant auth object in SU21 and assign 1594 * the authorized functions to the user. Uncomment to implement security. 1595 * authority-check object 'Z_JSON' 1596 * id 'FMNAME' field funcname. 1597 * if sy-subrc ne 0. 1598 * http_error '403' 'Not authorized' 'You are not authorized to invoke this function module.'. 1599 * endif. 1600 1601 ***************************************************************************** 1602 * check CORS 1603 * see https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS * 1604 ***************************************************************************** 1605 1606 1607 1608 ****************** 1609 * get input data * 1610 ****************** 1611 CLEAR i_cdata. 1612 i_cdata = server->request->get_cdata( ). 1613 server->request->get_form_fields_cs( CHANGING fields = qs_nvp ). 1614 1615 * We map the query string to a simple JSON input. Handy for REST style queries. 1616 * The query string may come from GET requests in the url and content data in 1617 * POST request in x-www-form-urlencoded. ICF handles this perfectly and mixes both!! Great!! 1618 IF ( qs_nvp IS NOT INITIAL AND i_cdata IS INITIAL ) OR 1619 i_content_type CS 'application/x-www-form-urlencoded'. 1620 l_lines = lines( qs_nvp ). 1621 CLEAR l_idx. 1622 MOVE '{' TO i_cdata. 1623 LOOP AT qs_nvp ASSIGNING . 1624 ADD 1 TO l_idx. 1625 TRANSLATE -name TO UPPER CASE. " ABAP is upper case internally anyway. 1626 CONCATENATE i_cdata '"' -name '":"' -value '"' INTO i_cdata 1627 RESPECTING BLANKS. 1628 IF l_idx < l_lines. 1629 CONCATENATE i_cdata ',' INTO i_cdata RESPECTING BLANKS. 1630 ENDIF. 1631 ENDLOOP. 1632 CONCATENATE i_cdata '}' INTO i_cdata. 1633 ENDIF. 1634 1635 1636 1637 * Prepare params to call function 1638 CALL METHOD zcl_json_handler=>build_params 1639 EXPORTING 1640 function_name = funcname 1641 IMPORTING 1642 params = t_params_p 1643 paramtab = paramtab 1644 exceptab = exceptab 1645 EXCEPTIONS 1646 invalid_function = 1 1647 OTHERS = 2. 1648 1649 IF sy-subrc <> 0. 1650 CONCATENATE 'Invalid Function. ' sy-msgid sy-msgty sy-msgno ': ' 1651 sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 1652 INTO etext SEPARATED BY '-'. 1653 http_error '500' 'Server Error' etext. 1654 ENDIF. 1655 1656 1657 ********************** 1658 * Process input data * 1659 ********************** 1660 TRY. 1661 CALL METHOD me->json_deserialize " The classic method using JavaScript (JSON only) 1662 * CALL METHOD me->deserialize_id " The new method using transformation id. This method accepts both JSON and XML input!!! Great!! 1663 EXPORTING 1664 json = i_cdata 1665 CHANGING 1666 paramtab = paramtab. 1667 1668 CATCH cx_root INTO oexcp. 1669 1670 etext = oexcp->if_message~get_text( ). 1671 1672 http_error '500' 'Internal Server Error' etext. 1673 1674 ENDTRY. 1675 */**********************************/* 1676 */**********************************/* 1677 1678 1679 1680 */************************************************/* 1681 */ Pass some request info to function module /* 1682 */ for FMs implementing a REST model or whatever /* 1683 */************************************************/* 1684 READ TABLE paramtab WITH KEY name = '_ICF_DATA' ASSIGNING . 1685 IF sy-subrc EQ 0. 1686 CREATE DATA -value TYPE zicf_handler_data. 1687 ASSIGN -value->* TO . 1688 -request_method = request_method. 1689 -icf_url = me->my_url. 1690 -icf_service = me->my_service. 1691 -path_info = path_info. 1692 -qs_tab = qs_nvp. 1693 -i_json_data = i_cdata. 1694 -camelcase_names = camelcase_names. 1695 APPEND '_ICF_DATA' TO -delete_params. 1696 -server = server. " Beware! 1697 ENDIF. 1698 1699 1700 1701 **************************** 1702 * Call the function module * 1703 **************************** 1704 TRY. 1705 "/afl/log_init. 1706 CALL FUNCTION funcname 1707 PARAMETER-TABLE 1708 paramtab 1709 EXCEPTION-TABLE 1710 exceptab. 1711 "/afl/save. 1712 CATCH cx_root INTO oexcp. 1713 1714 etext = oexcp->if_message~get_longtext( preserve_newlines = abap_true ). 1715 1716 http_error '500' 'Internal Server Error' etext. 1717 1718 ENDTRY. 1719 1720 1721 * Remove unused exceptions 1722 funcrc = sy-subrc. 1723 DELETE exceptab WHERE value NE funcrc. 1724 READ TABLE exceptab INTO exception WITH KEY value = funcrc. 1725 IF sy-subrc EQ 0. 1726 exceptheader = exception-name. 1727 CALL METHOD server->response->set_header_field( 1728 name = 'X-SAPRFC-Exception' 1729 value = exceptheader ). 1730 ENDIF. 1731 1732 1733 */*******************************************************************/* 1734 */ Read specific FM parameters for REST type interfaces /* 1735 */ I need to find a way on how to operate with some http codes: /* 1736 */ 201 Created - URI of resource created is set in Location header /* 1737 */ 202 Accepted - Response contains status information 1738 */ 203 Non-Authoritative Information 1739 */ 204 No Content - NO CONTENT is sent, nothing, nada 1740 */ 205 Reset Content - NO CONTENT is sent, nothing, nada 1741 */ 206 Partial Content - probably will not implement this 1742 */ Codes 3xx, 4xx should also be handled. 1743 */***********************************/* 1744 IF IS ASSIGNED. 1745 IF -http_code IS NOT INITIAL. 1746 server->response->set_status( code = -http_code reason = -http_status ). 1747 CASE -http_code. 1748 WHEN 204 OR 205. 1749 EXIT. 1750 WHEN OTHERS. " many to add? 1751 ENDCASE. 1752 ENDIF. 1753 IF -error_message IS NOT INITIAL. 1754 str_item = -http_code. CONDENSE str_item. 1755 http_error str_item -http_status -error_message. 1756 ENDIF. 1757 * read camelcase_names 1758 camelcase_names = -camelcase_names. 1759 * Delete indicated params for not showing them in the response 1760 LOOP AT -delete_params INTO dparam. 1761 DELETE paramtab WHERE name EQ dparam. 1762 ENDLOOP. 1763 ENDIF. 1764 1765 1766 * Prepare response. Serialize to output format stream. 1767 CASE format. 1768 1769 WHEN 'YAML'. 1770 1771 CALL METHOD me->serialize_yaml 1772 EXPORTING 1773 paramtab = paramtab 1774 exceptab = exceptab 1775 params = t_params_p 1776 jsonp = jsonp_callback 1777 show_impp = show_import_params 1778 lowercase = lowercase 1779 IMPORTING 1780 yaml_string = o_cdata. 1781 1782 server->response->set_header_field( name = 'Content-Type' value = 'text/plain' ). 1783 1784 WHEN 'PERL'. 1785 1786 CALL METHOD me->serialize_perl 1787 EXPORTING 1788 paramtab = paramtab 1789 exceptab = exceptab 1790 params = t_params_p 1791 jsonp = jsonp_callback 1792 show_impp = show_import_params 1793 funcname = funcname 1794 lowercase = lowercase 1795 IMPORTING 1796 perl_string = o_cdata. 1797 1798 server->response->set_header_field( name = 'Content-Type' value = 'text/plain' ). 1799 1800 WHEN 'XML'. 1801 1802 CALL METHOD me->serialize_xml 1803 * CALL METHOD me->serialize_id 1804 EXPORTING 1805 paramtab = paramtab 1806 exceptab = exceptab 1807 params = t_params_p 1808 jsonp = jsonp_callback 1809 show_impp = show_import_params 1810 funcname = funcname 1811 lowercase = lowercase 1812 format = format 1813 IMPORTING 1814 o_string = o_cdata. 1815 1816 server->response->set_header_field( name = 'Content-Type' value = 'application/xml' ). 1817 1818 WHEN OTHERS. " the others default to JSON. 1819 1820 format = 'JSON'. 1821 CALL METHOD me->serialize_json 1822 * CALL METHOD me->serialize_id 1823 EXPORTING 1824 paramtab = paramtab 1825 exceptab = exceptab 1826 params = t_params_p 1827 jsonp = jsonp_callback 1828 show_impp = show_import_params 1829 lowercase = lowercase 1830 camelcase = camelcase 1831 camelcase_names = camelcase_names 1832 * format = format 1833 IMPORTING 1834 o_string = o_cdata. 1835 1836 server->response->set_header_field( name = 'Content-Type' value = 'application/json' ). 1837 IF jsonp_callback IS NOT INITIAL. 1838 server->response->set_header_field( name = 'Content-Type' value = 'application/javascript' ). 1839 ENDIF. 1840 1841 ENDCASE. 1842 1843 1844 * Set response: 1845 server->response->set_header_field( name = 'X-Data-Format' value = format ). " 1846 * Activate compression (will compress when size>1kb if requested by client in Accept-Encoding: gzip. Very nice.). 1847 server->response->set_compression( ). 1848 * if -alt_response is not initial. 1849 * o_cdata =-alt_response. 1850 * endif. 1851 server->response->set_cdata( data = o_cdata ). 1852 1853 ******************************************* 1854 ******************************************* 1855 ********** * * ********* 1856 ********* * * ********** 1857 ******** * * *********** 1858 ******************************************* 1859 ******************************************* 1860 ENDMETHOD. 1861 1862 1863 *---------------------------------------------------------------------------------------+ 1864 * | Static Public Method ZCL_JSON_HANDLER=>JSON2ABAP 1865 * +-------------------------------------------------------------------------------------------------+ 1866 * | [--->] JSON_STRING TYPE STRING(optional) 1867 * | [--->] VAR_NAME TYPE STRING(optional) 1868 * | [--->] PROPERTY_PATH TYPE STRING (default ='json_obj') 1869 * | [<---] PROPERTY_TABLE TYPE JS_PROPERTY_TAB 1870 * | [<-->] JS_OBJECT TYPE REF TO CL_JAVA_SCRIPT(optional) 1871 * | [<-->] ABAP_DATA TYPE ANY(optional) 1872 * | [!CX!] ZCX_JSON 1873 * +-------------------------------------------------------------------------------------- 1874 method JSON2ABAP. 1875 */************************************************/* 1876 */ Input any abap data and this method tries to /* 1877 */ fill it with the data in the JSON string. /* 1878 */ Thanks to Juan Diaz for helping here!! /* 1879 */************************************************/* 1880 1881 type-pools: abap, js. 1882 1883 data: 1884 js_script type string, 1885 js_started type i value 0, 1886 l_json_string type string, 1887 js_property_table type js_property_tab, 1888 js_property type line of js_property_tab, 1889 l_property_path type string, 1890 compname type string, 1891 item_path type string. 1892 1893 data: 1894 l_type type c, 1895 l_value type string, 1896 linetype type string, 1897 l_comp type line of ABAP_COMPDESCR_TAB. 1898 1899 data: 1900 datadesc type ref to CL_ABAP_TYPEDESCR, 1901 drefdesc type ref to CL_ABAP_TYPEDESCR, 1902 linedesc type ref to CL_ABAP_TYPEDESCR, 1903 strudesc type ref to CL_ABAP_STRUCTDESCR, 1904 tabldesc type ref to CL_ABAP_TABLEDESCR. 1905 1906 data newline type ref to data. 1907 1908 field-symbols: 1909type any, 1910 type any table, 1911 type any, 1912 type line of js_property_tab, 1913 type abap_compdescr. 1914 1915 1916 define assign_scalar_value. 1917 " &1 1918 " &2 js_property-value 1919 describe field &1 type l_type. 1920 l_value = &2. 1921 * convert or adapt scalar values to ABAP. 1922 case l_type. 1923 when 'D'. " date type 1924 if l_value cs '-'. 1925 replace all occurrences of '-' in l_value with space. 1926 condense l_value no-gaps. 1927 endif. 1928 when 'T'. " time type 1929 if l_value cs ':'. 1930 replace all occurrences of ':' in l_value with space. 1931 condense l_value no-gaps. 1932 endif. 1933 when others. 1934 " may be other conversions or checks could be implemented here. 1935 endcase. 1936 &1 = l_value. 1937 end-of-definition. 1938 1939 1940 if js_object is not bound. 1941 1942 if json_string is initial. exit. endif. " exit method if there is nothing to parse 1943 1944 l_json_string = json_string. 1945 " js_object = cl_java_script=>create( STACKSIZE = 16384 ). 1946 js_object = cl_java_script=>create( STACKSIZE = 16384 HEAPSIZE = 960000 ). 1947 1948 *************************************************** 1949 * Parse JSON using JavaScript * 1950 *************************************************** 1951 js_object->bind( exporting name_obj = 'abap_data' name_prop = 'json_string' changing data = l_json_string ). 1952 js_object->bind( exporting name_obj = 'abap_data' name_prop = 'script_started' changing data = js_started ). 1953 1954 * We use the JavaScript engine included in ABAP to read the JSON string. 1955 * We simply use the recommended way to eval a JSON string as specified 1956 * in RFC 4627 (http://www.ietf.org/rfc/rfc4627.txt). 1957 * 1958 * Security considerations: 1959 * 1960 * Generally there are security issues with scripting languages. JSON 1961 * is a subset of JavaScript, but it is a safe subset that excludes 1962 * assignment and invocation. 1963 * 1964 * A JSON text can be safely passed into JavaScript's eval() function 1965 * (which compiles and executes a string) if all the characters not 1966 * enclosed in strings are in the set of characters that form JSON 1967 * tokens. This can be quickly determined in JavaScript with two 1968 * regular expressions and calls to the test and replace methods. 1969 * 1970 * var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test( 1971 * text.replace(/"(\\.|[^"\\])*"/g, ''))) && 1972 * eval('(' + text + ')'); 1973 1974 concatenate 1975 1976 'var json_obj; ' 1977 'var json_text; ' 1978 1979 'function start() { ' 1980 ' if(abap_data.script_started) { return; } ' 1981 ' json_text = abap_data.json_string;' 1982 ' json_obj = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test( ' 1983 ' json_text.replace(/"(\\.|[^"\\])*"/g, ''''))) && ' 1984 ' eval(''('' + json_text + '')''); ' 1985 ' abap_data.script_started = 1; ' 1986 '} ' 1987 1988 'if(!abap_data.script_started) start(); ' 1989 1990 1991 into js_script respecting blanks separated by xnl. 1992 1993 js_object->compile( script_name = 'json_parser' script = js_script ). 1994 js_object->execute( script_name = 'json_parser' ). 1995 1996 if js_object->last_error_message is not initial. 1997 RAISE EXCEPTION type zcx_json 1998 EXPORTING 1999 message = js_object->last_error_message. 2000 endif. 2001 2002 endif. 2003 ** End of JS processing. 2004 2005 ** 2006 if var_name is not initial. 2007 concatenate property_path var_name into l_property_path separated by '.'. 2008 else. 2009 l_property_path = property_path. 2010 endif. 2011 ** 2012 ** 2013 js_property_table = js_object->get_properties_scope_global( property_path = l_property_path ). 2014 property_table = js_property_table. 2015 2016 * Exit if abap_data is not supplied, normally when called 2017 * from json_deserialize to get top level properties 2018 if abap_data is not supplied. 2019 exit. 2020 endif. "*** 2021 2022 * 2023 * Get ABAP data type, dereference if necessary and start 2024 datadesc = cl_abap_typedescr=>DESCRIBE_BY_DATA( abap_data ). 2025 if datadesc->kind eq cl_abap_typedescr=>kind_ref. 2026 assign abap_data->* to . 2027 else. 2028 assign abap_data to . 2029 endif. 2030 datadesc = cl_abap_typedescr=>DESCRIBE_BY_DATA( ). 2031 2032 2033 case datadesc->kind. 2034 2035 when cl_abap_typedescr=>kind_elem. 2036 * Scalar: process ABAP elements. Assume no type conversions for the moment. 2037 if var_name is initial. 2038 RAISE EXCEPTION type zcx_json 2039 EXPORTING 2040 message = 'VAR_NAME is required for scalar values.'. 2041 endif. 2042 js_property_table = js_object->get_properties_scope_global( property_path = property_path ). 2043 read table js_property_table with key name = var_name into js_property. 2044 if sy-subrc eq 0. 2045 assign_scalar_value js_property-value. 2046 endif. 2047 2048 2049 when cl_abap_typedescr=>kind_struct. 2050 * Process ABAP structures 2051 strudesc ?= datadesc. 2052 loop at js_property_table assigning . 2053 compname = -name. 2054 translate compname to upper case. 2055 read table strudesc->COMPONENTS with key name = compname into l_comp. 2056 if sy-subrc eq 0. 2057 assign component l_comp-name of structure to . 2058 case l_comp-type_kind. 2059 when cl_abap_typedescr=>TYPEKIND_STRUCT1 " 'v' 2060 or cl_abap_typedescr=>TYPEKIND_STRUCT2 " 'u' 2061 or cl_abap_typedescr=>TYPEKIND_TABLE. " 'h' (may need a different treatment one day) 2062 concatenate l_property_path -name into item_path separated by '.'. 2063 *> Recursive call here 2064 json2abap( exporting property_path = item_path changing abap_data = js_object = js_object ). 2065 2066 when others. 2067 * Process scalars in structures (same as the kind_elem above) 2068 assign_scalar_value -value. 2069 2070 endcase. 2071 endif. 2072 endloop. 2073 2074 when cl_abap_typedescr=>kind_table. 2075 * Process ABAP tables 2076 if js_property_table is not initial. 2077 tabldesc ?= datadesc. 2078 linedesc = tabldesc->get_table_line_type( ). 2079 linetype = linedesc->get_relative_name( ). 2080 assign to . 2081 loop at js_property_table into js_property where name NE 'length'. " the JS object length 2082 create data newline type (linetype). 2083 assign newline->* to . 2084 case js_property-kind. 2085 when 'O'. 2086 concatenate l_property_path js_property-name into item_path separated by '.'. 2087 condense item_path. 2088 *> Recursive call here 2089 json2abap( exporting property_path = item_path changing abap_data = newline js_object = js_object ). 2090 when others. " Assume scalars, 'S', 'I', or other JS types 2091 " Process scalars in plain table components(same as the kind_elem above) 2092 assign_scalar_value js_property-value. 2093 endcase. 2094 insert into table . 2095 free newline. 2096 endloop. 2097 endif. 2098 2099 when others. " kind_class, kind_intf 2100 " forget it. 2101 2102 endcase. 2103 2104 2105 endmethod. 2106 2107 2108 * ---------------------------------------------------------------------------------------+ 2109 * | Static Public Method ZCL_JSON_HANDLER=>JSON_DESERIALIZE 2110 * +-------------------------------------------------------------------------------------------------+ 2111 * | [--->] JSON TYPE STRING 2112 * | [<-->] PARAMTAB TYPE ABAP_FUNC_PARMBIND_TAB 2113 * | [!CX!] ZCX_JSON 2114 * +-------------------------------------------------------------------------------------- 2115 method JSON_DESERIALIZE. 2116 2117 type-pools: ABAP, JS. 2118 2119 ** Remember function parameter types 2120 **constants: 2121 ** abap_func_exporting type abap_func_parmbind-kind value 10, 2122 ** abap_func_importing type abap_func_parmbind-kind value 20, 2123 ** abap_func_tables type abap_func_parmbind-kind value 30, 2124 ** abap_func_changing type abap_func_parmbind-kind value 40. 2125 2126 data paramname type string. 2127 data js_obj type ref to cl_java_script. 2128 data js_prop_tab type js_property_tab. 2129 2130 field-symbolstype line of js_property_tab. 2131 field-symbols type abap_func_parmbind. 2132 2133 if json is initial. exit. endif. 2134 2135 json2abap( exporting json_string = json importing property_table = js_prop_tab changing js_object = js_obj ). 2136 2137 loop at js_prop_tab assigning . 2138 paramname = -name. 2139 translate paramname to upper case. 2140 read table paramtab with key name = paramname assigning . 2141 if sy-subrc eq 0. 2142 if -kind ne abap_func_importing. "" va al revés, cuidado!!! 2143 json2abap( exporting var_name = -name changing abap_data = -value js_object = js_obj ). 2144 endif. 2145 endif. 2146 endloop. 2147 2148 endmethod. 2149 2150 2151 * ---------------------------------------------------------------------------------------+ 2152 * | Instance Public Method ZCL_JSON_HANDLER->NOTES 2153 * +-------------------------------------------------------------------------------------------------+ 2154 * | [<-()] TEXT TYPE STRING 2155 * +-------------------------------------------------------------------------------------- 2156 method NOTES. 2157 2158 data location type string. 2159 2160 concatenate me->my_url me->my_service '/RFC_SYSTEM_INFO' into location. 2161 2162 concatenate 2163 2164 'JSON (NEW) handler notes ' 2165 2166 'About this service...
' 2167 'This is the ABAP implementation of a conversion program that' 2168 ' tranforms ABAP data into a JSON representation.' 2169 '' 2170 'It provides a user interface in the form of a ICF service that ' 2171 'allows web invocation of ABAP function modules. It doesn''t matter if they are RFC enabled or not.' 2172 'In this system this service has
' 2173 'been assigned to ICF service ' me->my_url me->my_service '">' me->my_service '.' 2174 '' 2175 'In order to invoke a function module, just put its name in the PATH_INFO ' 2176 'of the service URL, as is shown in the following examples.' 2177 2178 'Try the following link to do the default call in JSON format:
'location '?format=json">' 2179 location 2180 '?format=json
A simple syntax allows to get the output in different formats.
' 2183 2184 'The following gets the output in YAML format:' 2185 ''location '?format=yaml">' 2186 location 2187 '?format=yaml' 2188 '' 2189 '
And this will get the output in a basic XML representation:
'location '?format=xml">' 2190 location 2191 '?format=xml' 2192 2193 '
And, just for fun, getting it into Perl format could be handy:
'location '?format=perl">' 2194 location 2195 '?format=perl' 2196 2197 '
Finnally, you can add a callback to get the JSON response enclosed in a javascript function call,
' 2198 ' in order to allow a JSONP style response: ' 2199 ''2200 location '?format=json&callback=callMe">' 2201 location '?format=json&callback=callMe' 2202 2203 '
WARNING
This is work in progress and may not be suitable for use in productive ' 2204 'systems. The interface is somewhat unstable. Please feel free to test it and report ' 2205 'any bug and improvement you may find.' 2206 'Use it at your own risk!
' 2207 '' 2208 'https://cw.sdn.sap.com/cw/groups/json-adapter-for-abap-function-modules' 2209 '' 2210 'If you have any questions, please contact me at ' 2211 'cesar.martin@sap.com' 2212 '' 2213 2214 2215 '' 2216 2217 2218 into text RESPECTING BLANKS. 2219 2220 2221 endmethod. 2222 2223 2224 *
SICF新建服务节点:
在 /sap/bc/节点下新建子节点ABAPAPI,在处理器清单中添加自定义类:ZCL_JSON_HANDLER,在登录数据中配置SAP的接口账号密码,最后激活服务,右键点击测试
测试出现如下信息,表示内网环境下已配置成功。
接下来在POSTMAN中调用测试
在JAVA中测试:
JAVA中测试代码:
1 package com.chenh.restful.test; 2 import java.io.BufferedReader; 3 import java.io.IOException; 4 import java.io.InputStreamReader; 5 import java.io.OutputStreamWriter; 6 import java.net.HttpURLConnection; 7 import java.net.MalformedURLException; 8 import java.net.URL; 9 import java.nio.charset.Charset; 10 import org.apache.tomcat.util.codec.binary.Base64; 11 12 public class RFC_READ_TABLE { 13 14 public static void main(String[] args) { 15 String URL = "http://xxxx.xxxx.xxxx.xxxx:8000/sap/bc/abapapi/"; 16 String FNAME = "RFC_READ_TABLE"; 17 String json = "{\"QUERY_TABLE\":\"T001\",\"ROWCOUNT\":\"2\"}"; 18 19 String USERNAME = "XXXXXXX"; 20 String PASSWORD = "XXXXXXX"; 21 String auth = USERNAME + ":" + PASSWORD; 22 String authHeader = "Basic " + new String(Base64.encodeBase64(auth.getBytes(Charset.forName("US-ASCII")))); 23 HttpURLConnection conn = null; 24 OutputStreamWriter out = null; 25 BufferedReader in = null; 26 StringBuilder result = new StringBuilder(); 27 String line; 28 try { 29 URL url = new URL(URL + FNAME); 30 conn = (HttpURLConnection) url.openConnection(); 31 conn.setRequestProperty("Content-Type", "application/json"); 32 conn.setRequestProperty("Accept", "application/json"); 33 conn.setRequestProperty("Authorization", authHeader); 34 conn.setRequestMethod("POST"); 35 conn.setConnectTimeout(6000); 36 conn.setReadTimeout(6000); 37 conn.setDoOutput(true); 38 conn.setDoInput(true); 39 out = new OutputStreamWriter(conn.getOutputStream()); 40 out.write(json); 41 out.flush(); 42 out.close(); 43 if (200 == conn.getResponseCode()) { 44 in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); 45 while ((line = in.readLine()) != null) { 46 result.append(line); 47 } 48 } else { 49 System.out.println("发送失败:" + conn.getResponseCode()); 50 } 51 } catch (MalformedURLException e) { 52 e.printStackTrace(); 53 } catch (IOException e) { 54 e.printStackTrace(); 55 } 56 System.out.println(result.toString()); 57 } 58 }