Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
horst_keller
Product and Topic Expert
Product and Topic Expert
32,918

Facts

  • Simple Transformations (ST) serialize ABAP to XML and deserialize XML to ABAP.
  • JSON-writers of the sXML-Library consume JSON-XML and digest it to JSON.
  • The statement CALL TRANSFORMATION handles JSON-sources as JSON-XML implicitly.

Conclusion

The result of an ST that produces JSON-XML can be fed into a JSON writer to produce JSON. The same transformation can be used to deserialize JSON directly (a JSON-reader could be switched in between, but is not necessary).

Example ST producing or consuming JSON-XML

<?sap.transform simple?>

<tt:transform xmlns:tt="http://www.sap.com/transformation-templates">
  <tt:root name="CARRIERS"/>
  <tt:template>
    <array>
      <tt:loop ref=".CARRIERS">
        <object>
          <str name="Carrier-Id">
            <tt:value ref="$ref.carrid"/>
          </str>
          <str name="Carrier">
            <tt:value ref="$ref.carrname"/>
          </str>
          <str name="URL">
            <tt:value ref="$ref.url"/>
          </str>
        </object>
      </tt:loop>
    </array>
  </tt:template>
</tt:transform>

Example ABAP calling ST

CLASS demo DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS main.
  PRIVATE SECTION.
    CLASS-METHODS: display_as_text
                    IMPORTING json TYPE xstring,
                  display_as_html
                    IMPORTING json TYPE xstring.
ENDCLASS.

CLASS demo IMPLEMENTATION.
  METHOD main.

    "Get some data into an internal table
    TYPES: BEGIN OF carrier,
            carrid  TYPE scarr-carrid,
            carrname TYPE scarr-carrname,
            url      TYPE scarr-url,
          END OF carrier.
    DATA carriers TYPE TABLE OF carrier.
    SELECT carrid carrname url
          FROM scarr
          INTO CORRESPONDING FIELDS OF TABLE carriers.

    "Create JSON-writer and call simple transformation
    DATA json_writer TYPE REF TO cl_sxml_string_writer.
    DATA writer TYPE REF TO if_sxml_writer.
    json_writer = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).
    writer ?= json_writer.
    writer->set_option( option = if_sxml_writer=>co_opt_linebreaks ).
    writer->set_option( option = if_sxml_writer=>co_opt_indent ).
    CALL TRANSFORMATION demo_st_json_table SOURCE carriers = carriers
                                    RESULT XML json_writer.

    "Get JSON-String from writer
    DATA json TYPE xstring.
    json = json_writer->get_output( ).

    "Two ways of displaying the JSON string
    display_as_text( json ).
    display_as_html( json ).

    "Back to ABAP, verify that transformation is symmetric

    DATA result LIKE carriers.
    CALL TRANSFORMATION demo_st_json_table SOURCE XML json
                                    RESULT carriers = result.
   
ASSERT result = carriers.

  ENDMETHOD.
  METHOD display_as_text.
    "Simple output of JSON in text edit control
    DATA text TYPE string.
    text = cl_abap_codepage=>convert_from( json ).
    cl_demo_text=>show_string( text ).
  ENDMETHOD.
  METHOD display_as_html.
    "Beautified output of JSON in HTML browser
    DATA html TYPE string.
    CALL TRANSFORMATION sjson2html SOURCE XML json
                                  RESULT XML html.
    cl_abap_browser=>show_html( html_string = html ).
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  demo=>main( ).

Note

If you replace type = if_sxml=>co_xt_json with type = if_sxml=>co_xt_xml10 when creating the sXML-writer, it becomes an XML-writer and you will get JSON-XML instead of JSON from the writer.

14 Comments
SatheeshKumara1
Participant
0 Kudos

well done Horst

thx...

former_member183924
Active Participant
0 Kudos

I couldn't find CL_DEMO_TEXT=>SHOW_STRING method on a 7.31SP02 CRM system. So I had to implement DISPLAY_AS_TEXT method in a different way, which I want to share here:

    DATA: lv_text TYPE string,
           lt_text TYPE cl_demo_text=>t_text,
           lo_text TYPE REF TO cl_demo_text.


     lv_text = cl_abap_codepage=>convert_from( json ).

     CALL FUNCTION 'SCMS_STRING_TO_FTEXT'
       EXPORTING
         text            = lv_text
       TABLES
         ftext_tab       = lt_text.

     lo_text = cl_demo_text=>get_handle( ).
     lo_text->add_table( lt_text ).
     lo_text->display(  ).

--

Steffen

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

Yep, CL_DEMO_TEXT=>SHOW_STRING comes to 7.31 with SP07 or so. But its purely "Demo"  anyway ...

Former Member
0 Kudos

Hello Horst, this is a bit off-topic, but anyway: Will Transformations always have to be program objects, or will be ever be able to compile a transformation from a string in an ABAP program? (Or is this perhaps possible now already?)

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi Martin,

Good Idea, but not yet possible in 7.40 and I don't know about any plans for that.

Best Horst

PS: In the 8.0x-Release-Line (see ABAP News for Release 7.40 - What is ABAP 7.40?) we have already some dynamic transformation features, e.g. a  dynamic mapping in ST. We also have a thing called AMS (ABAP Mapping Script for mappings between ABAP data) that works exactly like you described it (script in a string). Let's see if some of those will come down to 7.40 somewhere, sometime ...

Former Member
0 Kudos

Dear Horst,

Do I need to create different STs for different types of internal tables, My requirement is to convert any internal table to a JSON string. is there a way out, the code should be generic.

Thanks,

Raghavendra

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi Raghavendra,

If you want to convert any internal table to a JSON string, you can use the canonical

asJSON-Format that defines a predefined mapping of any ABAP data type to JSON.

You can either use

  • Inside a selfwritten ST, you can use tt:copy to create asXML and from there you can come to JSON-XML for asJSON.

Best

Horst

Former Member
0 Kudos

Hello Keller,

I need to call an Jason API from SAP ABAP.

I was trying the code you have provided, but am getting following error  -

' Transformation "SCARR_2_JSON" has no active version'


Can you please provide me your e-mail id on which i can share my code with you ? it will be big help.


Thanks

Vijay

horst_keller
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi,

you have to copy the above example transformation into an own Z_...-transformation in SE80 or STRANS and then call this transformation instead of the dummy name SCARR_2_JSON (which does not exist).

You might also try transformation DEMO_ST_JSON_TABLE that is available in recent releases.

Horst

PS: I replaced the transformation name SCARR_2_JSON with the existing transformation DEMO_ST_JSON_TALBE above.

matt
Active Contributor
0 Kudos

I used this as the basis for my first ever simple transformation. I had a problem though, in that some of my JSON data was str and at other times null

(i.e. "ParameterID":"ABCE" or "ParameterID:null")

The solution was to use switch with cond-d - sample code is here: Simple Transformation - handling null values

Former Member
0 Kudos
Can someone explain how to define a transformation for a nested JSON where the nested object is not an array but a single object?

 

e.g. -

{

"car" : "Porshe" ,

"owner" : {

"first" : "John",

"last" : "Doe"

}

}

 

It would be really helpful. Thanks in advance.
former_member206439
Contributor
0 Kudos
I have a requirement to Transform Deep structure with KSON format, Header and Item relation, Could you please help me?
ttrapp
Active Contributor
0 Kudos
In NW 7.50 this is possible:
<?sap.transform simple?>
<tt:transform xmlns:tt="http://www.sap.com/transformation-templates">

<tt:root name="ROOT"/>
<tt:template>
<object>
<str name="car">
<tt:value ref="ROOT.car"/>
</str>

<object name="owner">
<str name="first">
<tt:value ref="ROOT.first"/>
</str>
<str name="last">
<tt:value ref="ROOT.last"/>
</str>
</object>

</object>
</tt:template>
</tt:transform>

The data root ROOT is a structure containing components car, first, last.

 

 
johnm16
Participant
0 Kudos
Hi Horst,

sorry to respond to an ancient blog (although that makes it no less valuable), but I have an ST question you may be able to answer.

I have several STs for transforming JSON strings into ABAP data.  They work fine, except for one where the (external) sender has just changed the sequence of the key pairs in one of the structures.

As I understood it, the definition for JSON data is that within an object, key pairs can be supplied in any order.  How does this fit with a simple transformation where the key pairs are defined in a particular sequence?

Kind regards,

John Moulding.
Labels in this area