2

我创建这样的 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=>serialize( )并不好。

4

4 回答 4

2

如果您真的想将它用作提取表记录的工具,那么您可以IDSTRANS. 它可能看起来像这样,让我们​​命名它Z_JSON_TABLE_CONTENTS(使用 type 创建它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 ).
于 2019-03-31T18:43:49.113 回答
1

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

现在,有了KISS 原则的解决方案:

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 ``.
于 2019-03-30T14:10:13.193 回答
1

只需一点手工工作,瞧!

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` ).

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

于 2019-05-29T12:15:11.250 回答
0

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

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

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

于 2019-04-01T08:54:54.347 回答