首页 > 解决方案 > 使用 `CALL TRANSFORMATION` 在 ABAP 中自定义空值/初始值的序列化

问题描述

CALL TRANSFORMATION您可以使用该命令将 ABAP 结构序列化为 JSON 。是否有可能序列化null初始字段的值或忽略初始字段?

TYPES: BEGIN OF t_my_type,
         foo TYPE string,
         bar TYPE string,
       END OF t_my_type.

DATA ls_structure TYPE t_my_type.
ls_structure-foo = 'some value'.
ASSERT ls_structure-bar IS INITIAL.
DATA(lo_json_writer) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).
CALL TRANSFORMATION id SOURCE result = ls_structure RESULT XML lo_json_writer.
DATA(lv_json_xstring) = lo_json_writer->get_output( ).
WRITE cl_abap_codepage=>convert_from( source = lv_json_xstring ).

这个最小工作示例的结果是:

{
  "RESULT": {
    "FOO": "some value",
    "BAR": ""
  }
}

在其他语言(需要处理从 SAP 导出的 json)中,一个空字符串并不相同,""并且null确实需要我想避免的额外处理/处理。我想要这样的结果

{
  "RESULT": {
    "FOO": "some value",
    "BAR": null
  }
}

或忽略这样的初始值:

{
  "RESULT": {
    "FOO": "some value"
  }
}

我可以通过一些额外的规则CALL TRANSFORMATION来处理null/initial 值吗?

标签: jsontransformationabap

解决方案


纯 ABAP 语言没有空值的概念,除了空引用。最接近的“概念”是初始值

用于生成 JSON 格式的ID转换永远不会从初始值生成 JSON 值“null”。空引用的序列化产生{},而其他类型产生""(类型 C、STRING、X、XSTRING,最后两个用 base64 表示)、"000..."(类型 N)、"0000-00-00"(类型 D)、"00:00:00"(类型 T)或0(类型I, P, F, DECFLOAT16, DECFLOAT34, INT1, INT2, INT8)。

要仅序列化非初始值,您可以使用以下选项 initial_components = 'suppress'CALL TRANSFORMATION

CALL TRANSFORMATION ID 
  SOURCE result = ls_structure 
  RESULT XML lo_json_writer
  OPTIONS initial_components = 'suppress'.

下面的程序演示了 JSON 值的区别,它们是初始值还是非初始值,以及何时使用选项initial_components = 'suppress'。注意:为了序列化数据引用,我必须使用选项“data_refs = 'heap-or-create'`。

  • 初始值:{"RESULT":{"STRING":"","CHAR4":"","INT":0,"BINFLOAT":0,"DECFLOAT":0,"NUMC4":"0000","DATE":"0000-00-00","TIME":"00:00:00","XSTRING":"","HEX2":"","DREF":{},"OREF":{}}}
  • 初始值 + 选项initial_components = 'suppress'{"RESULT":{}}
  • 非初始值:{"RESULT":{"STRING":"a ","CHAR4":"b","INT":-1,"BINFLOAT":-2.9999999999999999E-1,"DECFLOAT":-0.3,"NUMC4":"0001","DATE":"2019-11-01","TIME":"10:49:00","XSTRING":"/w==","HEX2":"/w==","DREF":{"%ref":"#d1"},"OREF":{"%ref":"#o10"}},"%heap":{"o10":{"%type":"http://www.sap.com/abapxml/classes/program/ZDEMO_JSON_INITIAL:LCL_CLASS","%val":{"local.LCL_CLASS":{"ATTRIBUTE":"d"}}},"d1":{"%type":"abap:characters","%maxLength":1,"%val":"c"}}}

程序:

REPORT zdemo_json_initial.
TYPES: BEGIN OF t_my_type,
        string   TYPE string,
        char4    TYPE c LENGTH 4,
        int      TYPE i,
        binfloat TYPE f,
        decfloat TYPE decfloat16,
        numc4    TYPE n LENGTH 4,
        date     TYPE d,
        time     TYPE t,
        xstring  TYPE xstring,
        hex2     TYPE x LENGTH 2,
        dref     TYPE REF TO data,
        oref     TYPE REF TO object,
      END OF t_my_type.
CLASS lcl_class DEFINITION.
  PUBLIC SECTION.
    INTERFACES if_serializable_object.
    DATA attribute TYPE string.
ENDCLASS.

DATA(initial) = value t_my_type( ).
DATA(oref) = NEW lcl_class( ).
oref->attribute = 'd'.
DATA(non_initial) = VALUE t_my_type( string = `a ` char4 = `b ` int = -1 binfloat = '-0.3'
    decfloat = '-0.3' numc4 = '1' date = '20191101' time = '104900'
    xstring = 'FF' hex2 = 'FF' dref = REF #( 'c' ) oref = oref ).

DATA(lo_json_writer1) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).
CALL TRANSFORMATION id SOURCE result = initial RESULT XML lo_json_writer1
    OPTIONS data_refs = 'heap-or-create'.
DATA(json_initial) = lo_json_writer1->get_output( ).

DATA(lo_json_writer2) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).
CALL TRANSFORMATION id SOURCE result = initial RESULT XML lo_json_writer2
    OPTIONS data_refs = 'heap-or-create' INITIAL_COMPONENTS = 'suppress'.
DATA(json_initial_suppress) = lo_json_writer2->get_output( ).

DATA(lo_json_writer3) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).
CALL TRANSFORMATION id SOURCE result = non_initial RESULT XML lo_json_writer3
    OPTIONS data_refs = 'heap-or-create'.
DATA(json_non_initial) = lo_json_writer3->get_output( ).

推荐阅读