【问题标题】:Customize JSON created by CL_SXML_STRING_WRITER自定义由 CL_SXML_STRING_WRITER 创建的 JSON
【发布时间】:2019-03-29 13:32:11
【问题描述】:

我创建这样的 JSON 来提取任何表(名称“随机”在运行时决定,其名称在变量 iv_table_name 中):

FIELD-SYMBOLS <itab> TYPE STANDARD TABLE.
DATA ref_itab TYPE REF TO data.

DATA(iv_table_name) = 'SCARR'.
CREATE DATA ref_itab TYPE STANDARD TABLE OF (iv_table_name).
ASSIGN ref_itab->* TO <itab>.

SELECT *
  INTO TABLE <itab>
  FROM (iv_table_name).

DATA results_json TYPE TABLE OF string.
DATA sub_json TYPE string.

DATA(lo_json_writer) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).

CALL TRANSFORMATION id
        SOURCE result = <itab>
        RESULT XML lo_json_writer.

cl_abap_conv_in_ce=>create( )->convert( 
        EXPORTING
          input = lo_json_writer->get_output( )
        IMPORTING
          data = sub_json ).

结果变量sub_json 如下所示:

{"RESULT":
 [
   {"MANDT":"220","AUFNR":"0000012", ...},
   {"MANDT":"220","AUFNR":"0000013", ...},
   ...
  ]
}

有没有办法避开周围的字典,得到这样的结果?

 [
   {"MANDT":"220","AUFNR":"0000012", ...},
   {"MANDT":"220","AUFNR":"0000013", ...},
   ...
  ]

背景:

我用过这个:

sub_json = /ui2/cl_json=>serialize( data = <lt_result> pretty_name = /ui2/cl_json=>pretty_mode-low_case ).

但是/ui2/cl_json=&gt;serialize( )的性能不好。

【问题讨论】:

  • 可能只是另一个转换。当我有更多时间时,我会发布我的建议。
  • 你可以通过只删除开始和结束部分来做 KISS 方式

标签: json abap json-serialization


【解决方案1】:

如果您真的想将它用作提取表记录的工具,那么您可以在STRANS 中编写自己的ID 转换。它可能看起来像这样,让我们​​将其命名为Z_JSON_TABLE_CONTENTS(使用XSLT 类型创建它):

<xsl:transform version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:sap="http://www.sap.com/sapxsl"
>

<xsl:output method="text" encoding="UTF-8" />

<xsl:strip-space elements="*"/>

<xsl:template match="RESULT">
  [
    <xsl:for-each select="*">
      {
      <xsl:for-each select="*">
        &quot;<xsl:value-of select="local-name()" />&quot;: &quot;<xsl:value-of select="text()" />&quot;<xsl:if test="position() != last()">,</xsl:if>
      </xsl:for-each>
      }<xsl:if test="position() != last()">,</xsl:if>
    </xsl:for-each>
  ]
</xsl:template>

</xsl:transform>

那你就可以这样用了。

REPORT ZZZ.

FIELD-SYMBOLS <itab> TYPE STANDARD TABLE.
DATA ref_itab TYPE REF TO data.

DATA(iv_table_name) = 'SCARR'.
CREATE DATA ref_itab TYPE STANDARD TABLE OF (iv_table_name).
ASSIGN ref_itab->* TO <itab>.

SELECT *
  INTO TABLE <itab>
  FROM (iv_table_name).

DATA results_json TYPE TABLE OF string.
DATA sub_json TYPE string.

DATA g_string TYPE string.
DATA(g_document) = cl_ixml=>create( )->create_document( ).
DATA(g_ref_stream_factory) = cl_ixml=>create( )->create_stream_factory( ).
DATA(g_ostream) = g_ref_stream_factory->create_ostream_cstring( g_string ).

CALL TRANSFORMATION Z_JSON_TABLE_CONTENTS
        SOURCE result = <itab>
        RESULT XML g_ostream.

DATA(g_json_parser) = new /ui5/cl_json_parser( ).
g_json_parser->parse( g_string ).

【讨论】:

    【解决方案2】:

    我不知道是否可以在完整的 sXML 中省略最初的“RESULT”标签,但我的意见是 NO。

    现在,KISS principle 有解决方案:

    REPLACE ALL OCCURRENCES OF REGEX '^\{"RESULT":|\}$' IN sub_json WITH ``.
    

    还有这个写法(稍慢):

    sub_json = replace( val = sub_json regex = '^\{"RESULT":|\}$' with = `` occ = 0 ).
    

    关于性能的附录:

    我测量了对于 880K 字符的字符串,以下代码具有要删除的确切位置数(10 个前导字符和 1 个尾随字符)比正则表达式快 6 倍(可能因 ABAP 内核版本而异),但与程序的其余部分相比,它可能并不明显:

    SHIFT sub_json LEFT BY 10 PLACES CIRCULAR.
    REPLACE SECTION OFFSET strlen( sub_json ) - 11 OF sub_json WITH ``.
    

    【讨论】:

      【解决方案3】:

      只是一点点手工工作,瞧!

      DATA(writer) = CAST if_sxml_writer( cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ) ).
      
      DATA(components) =
      CAST cl_abap_structdescr( cl_abap_typedescr=>describe_by_name( iv_table_name ) )->components.
      
      writer->open_element( name = 'object' ).
      LOOP AT <itab> ASSIGNING FIELD-SYMBOL(<line>).
       LOOP AT components ASSIGNING FIELD-SYMBOL(<fs_comp>).
        ASSIGN COMPONENT <fs_comp>-name OF STRUCTURE <line> TO FIELD-SYMBOL(<fs_val>).
        writer->open_element( name = 'str' ).
        writer->write_attribute( name = 'name' value = CONV string( <fs_comp>-name ) ).
        writer->write_value( CONV string( <fs_val> ) ).
        writer->close_element( ).
       ENDLOOP.
      ENDLOOP.
      writer->close_element( ).
      
      DATA(xml_json) = CAST cl_sxml_string_writer( writer )->get_output(  ).  
      sub_json = cl_abap_codepage=>convert_from( source = xml_json codepage = `UTF-8` ).
      

      没有周边列表,也没有字典。如果您想将每一行放在单独的字典中,它很容易调整。

      【讨论】:

        【解决方案4】:

        如果您使用ID 调用转换,那么您在转换时提供的任何节点都将默认添加该节点。我们不能跳过这个,但您可以通过以下方式删除..

        替换:使用正则表达式或直接词替换第一次出现语句和下一个最后一个右大括号}。你做的那样。

        FIND:您可以简单地使用以下语句 FIND REGEX '(\[.*\])' in sub_json SUBMATCHES sub_json.

        【讨论】:

        • 此外,您的 FIND 语句等效于使用 match 函数的赋值:sub_json = match( val = sub_json regex = '\[.*\]' ).
        猜你喜欢
        • 1970-01-01
        • 2022-09-30
        • 2019-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多