反序列化JSON xstring以在ABAP中进行结构化

时间:2020-02-26 11:04:06

标签: json sap abap

我想将JSON字符串反序列化为这样定义的结构:

TYPES: BEGIN OF json_subobject,
         c TYPE i,
         d TYPE decfloat34,
       END OF json_subobject.
TYPES: BEGIN OF json_object,
        a TYPE c LENGTH 10,
        b TYPE json_subobject,
       END OF json_object.

DATA: foo TYPE json_object.

我在JSON中对此结构进行建模,如下所示:

{
  "a":"FooBar",
  "b":{
    "c":9,
    "d":3.14
  }
}

现在,我编写了一个简单的程序来尝试对上述JSON以及上述结构定义进行CALL TRANSFORMATION语句。程序应反序列化JSON(硬编码到变量lv_xmls中)并打印出结果结构的内容。结构的内容应与原始JSON的内容匹配。这是程序:

TYPES: BEGIN OF json_subobject,
         c TYPE i,
         d TYPE decfloat34,
       END OF json_subobject.
TYPES: BEGIN OF json_object,
         a TYPE c LENGTH 10,
         b TYPE json_subobject,
       END OF json_object.

DATA: foo TYPE json_object.

DATA: lv_xmls TYPE string VALUE '{"a":"FooBar","b":{"c":9,"d":3.14}}',
      lv_xmlb TYPE xstring.

TRY.
    lv_xmlb = cl_abap_codepage=>convert_to(
                source      = lv_xmls
                codepage    = `UTF-8`
                endian      = space
                replacement = '#'
                ignore_cerr = abap_false ).
  CATCH cx_parameter_invalid_range cx_sy_codepage_converter_init cx_sy_conversion_codepage cx_parameter_invalid_type.
    ENDTRY.

WRITE: |Deserializing JSON ...|.
NEW-LINE.

CALL TRANSFORMATION id SOURCE XML lv_xmlb RESULT XML = foo.

WRITE: '{'.
NEW-LINE.
WRITE: |  "a": "{ foo-a }",|.
NEW-LINE.
WRITE: |  "b": \{|.
NEW-LINE.
WRITE: |    "c": { foo-b-c },|.
NEW-LINE.
WRITE: |    "d": { foo-b-d },|.
NEW-LINE.
WRITE: |  \}|.
NEW-LINE.
WRITE: |\}|.

我期望的输出是:

Deserializing JSON ...
{
  "a":"FooBar",
  "b":{
    "c":9,
    "d":3.14
  }
}

但是不幸的是,我得到的输出是:

Deserializing JSON ...
{
  "a":"",
  "b":{
    "c":0,
    "d":0
  }
}

CALL TRANSFORMATION语句对我没有任何作用。

是否有一个ABAP专家可以向我展示如何在这种(希望的)简单情况下使用CALL TRANSFORMATION?我已经环顾四周,发现this helpful GitHub repo演示了如何将JSON反序列化为一个类,但是为了简单起见,我更喜欢将JSON反序列化为一个结构。我不太确定如何使用CALL TRANSFORMATION,因为我不熟悉XSLT和高级XML功能,因此,如果可能的话,我非常感谢现有的解决方案...

非常感谢

约书亚

2 个答案:

答案 0 :(得分:4)

我的回答分为两个部分。据我介绍,第一个是最适合JSON的解决方案,第二个部分说明了为什么您的代码无法与CALL TRANSFORMATION ID一起使用。

PART 1:

您最好使用更适合处理JSON的SAP类之一。我更喜欢/UI2/CL_JSON类,它对我来说是最“开放”的类,因为它是SAP宣传最多的类(请参阅以下文档),尽管没有得到官方的支持(是的,很难理解,欢迎使用SAP世界)。

TYPES: BEGIN OF json_subobject,
         c TYPE i,
         d TYPE decfloat34,
       END OF json_subobject.
TYPES: BEGIN OF json_object,
         a TYPE c LENGTH 10,
         b TYPE json_subobject,
       END OF json_object.

DATA: foo TYPE json_object.

/ui2/cl_json=>deserialize(
    EXPORTING json = '{"a":"FooBar","b":{"c":9,"d":3.14}}'
    CHANGING  data = foo ).

ASSERT foo = VALUE json_object( 
    a   = 'FooBar' 
    b-c = 9 
    b-d = '3.14' ).

参考文档以获取更多信息:


PART 2:

您的CALL TRANSFORMATION ID代码无法正常工作有两个原因:

  1. JSON必须始终是具有以根名(RESULT rootname1 = var1 rootname2 = var2)命名的成员的JSON对象。您仅定义了一个名为“ XML”的根,所以JSON应该类似于{"X-ML":...}(由于特定的ABAP reason,它的名称为X-ML,而不是XML
  2. ABAP组件名称以大写字母(A,B,C,D)内部存储在SAP中,并且身份转换ID关于成员名称区分大小写,因此JSON数据的成员名称应大写(您的所有名称都用小写的a,b,c,d)。

不同地说,如果您输入的JSON包含以下值,您的代码可能会起作用:

lv_xmls = '{"X-ML":{"A":"FooBar","B":{"C":9,"D":3.14}}}'.

另一种解决方案可以包括创建一个自定义身份转换,该转换将JSON成员名称转换为大写并添加一个虚拟根元素。但这是另一个故事。

答案 1 :(得分:1)

我不是一个优秀的ABAP开发人员,所以我不知道是否有更好的代码可以这样做,但这对我有用:

    TYPES: BEGIN OF json_subobject,
         c TYPE i,
         d TYPE decfloat34,
       END OF json_subobject.
TYPES: BEGIN OF json_object,
         a TYPE c LENGTH 10,
         b TYPE json_subobject,
       END OF json_object.

DATA: foo TYPE json_object,
      writer TYPE REF TO cl_sxml_string_writer,
      json TYPE xstring.

DATA: lv_xmls TYPE string VALUE '{"a":"FooBar","b":{"c":9,"d":3.14}}',
      lv_xmlb TYPE xstring.

*TRY.
*    lv_xmlb = cl_abap_codepage=>convert_to(
*                source      = lv_xmls
*                codepage    = `UTF-8`
*                endian      = space
*                replacement = '#'
*                ignore_cerr = abap_false ).
*  CATCH cx_parameter_invalid_range cx_sy_codepage_converter_init cx_sy_conversion_codepage cx_parameter_invalid_type.
*    ENDTRY.



WRITE: |Deserializing JSON ...|.
NEW-LINE.

cl_fdt_json=>json_to_data( EXPORTING iv_json = lv_xmls
CHANGING ca_data = foo ).

WRITE: '{'.
NEW-LINE.
WRITE: |  "a": "{ foo-a }",|.
NEW-LINE.
WRITE: |  "b": \{|.
NEW-LINE.
WRITE: |    "c": { foo-b-c },|.
NEW-LINE.
WRITE: |    "d": { foo-b-d },|.
NEW-LINE.
WRITE: |  \}|.
NEW-LINE.
WRITE: |\}|.

此代码只是将JSON数组转换为内部表。