Skip to main content

Mapping (field renaming)

How it works

You can rename JSON attribute (node) names with a mapper. Typical example for this is making all attribute names upper/lower case or converting camel-snake naming styles (e.g. helloWorld -> hello_world).

  lo_orig_json = zcl_ajson=>parse( '{"ab":1,"bc":2}' ).
lo_new_json = lo_orig_json->map( li_mapper ). -> " E.g. '{"AB":1,"BC":2}'

" OR ... (but prefer the former, this one is deprected)
lo_new_json = zcl_ajson=>create_from(
ii_source_json = lo_orig_json
ii_mapper = li_mapper ).

... where li_mapper would be an instance of zif_ajson_mapping.

Ajson implements a couple of frequent convertors in zcl_ajson_mapping class, in particular:

  • upper/lower case
  • to camel case (camelCase)
  • to snake case (snake_case)

You can also implement you custom mapper. To do this you have to implement zif_ajson_mapping->rename_node(). It accepts the JSON nodes item-by-item and may change name via cv_name parameter. E.g.

  method zif_ajson_mapping~rename_field.
if cv_name+0(1) = 'a'. " Upper case all fields that start with "a"
cv_name = to_upper( cv_name ).
endif.
endmethod.

A realistic use case would be converting an external API result, which are often camel-cased (as this is very common in java-script world), and then converting it into ABAP structure:

  data:
begin of ls_api_response,
error_code type string,
...
end of ls_api_response.

lo_orig_json = zcl_ajson=>parse( lv_api_response_string ). " { "errorCode": 0, ... }
lo_new_json = lo_orig_json->map( zcl_ajson_mapping=>camel_to_snake( ) ).
lo_new_json->to_abap( importing ev_container = ls_api_response )

... or simpler and chained (combined with filter) ...

  zcl_ajson=>parse( lv_api_response_string
)->filter( zcl_ajson_filter_lib=>create_path_filter(
iv_skip_paths = '*/@*' " remove meta attributes
iv_pattern_search = abap_true ) )
)->map( zcl_ajson_mapping=>camel_to_snake( )
)->to_abap( importing ev_container = ls_api_response ).

"Boxed-in" mappers

Several typical mappers were implemented within zcl_ajson_mapping class:

  • upper case node names
zcl_ajson=>parse( '{"a":1,"b":{"c":2}}'
)->map( zcl_ajson_mapping=>create_upper_case( ) ).
" {"A":1,"B":{"C":2}}
  • lower case node names
zcl_ajson=>parse( '{"A":1,"B":{"C":2}}'
)->map( zcl_ajson_mapping=>create_lower_case( ) ).
" {"a":1,"b":{"c":2}}
  • rename nodes
" Purely by name
zcl_ajson=>parse( '{"a":1,"b":{"c":2},"d":{"e":3}}'
)->map( zcl_ajson_mapping=>create_rename( value #(
( from = 'a' to = 'x' )
( from = 'c' to = 'y' )
( from = 'd' to = 'z' ) )
) ).
" {"b":{"y":2},"x":1,"z":{"e":3}}

" Or by full path
zcl_ajson=>parse( '{"a":1,"b":{"a":2},"c":{"a":3}}'
)->map( zcl_ajson_mapping=>create_rename(
it_rename_map = value #( ( from = '/b/a' to = 'x' ) )
iv_rename_by = zcl_ajson_mapping=>rename_by-full_path
) ).
" {"a":1,"b":{"x":2},"c":{"a":3}}

" Or by pattern
zcl_ajson=>parse( '{"andthisnot":1,"b":{"thisone":2},"c":{"a":3}}'
)->map( zcl_ajson_mapping=>create_rename(
it_rename_map = value #( ( from = '/*/this*' to = 'x' ) )
iv_rename_by = zcl_ajson_mapping=>rename_by-pattern
) ).
" {"andthisnot":1,"b":{"x":2},"c":{"a":3}}
  • combine several arbitrary mappers together
zcl_ajson=>parse( '{"a":1,"b":{"a":2},"c":{"a":3}}'
)->map( zcl_ajson_mapping=>create_compound_mapper(
ii_mapper1 = zcl_ajson_mapping=>create_rename(
it_rename_map = value #( ( from = '/b/a' to = 'x' ) )
iv_rename_by = zcl_ajson_mapping=>rename_by-full_path )
ii_mapper2 = zcl_ajson_mapping=>create_upper_case( ) )
).
" {"A":1,"B":{"X":2},"C":{"A":3}}'
  • convert node names to snake case
zcl_ajson=>parse( '{"aB":1,"BbC":2,"cD":{"xY":3},"ZZ":4}'
)->map( zcl_ajson_mapping=>create_to_snake_case( ) ).
" {"a_b":1,"bb_c":2,"c_d":{"x_y":3},"zz":4}
  • convert node names to camel case
zcl_ajson=>parse( '{"a_b":1,"bb_c":2,"c_d":{"x_y":3},"zz":4}'
)->map( zcl_ajson_mapping=>create_to_camel_case( ) ).
" {"aB":1,"bbC":2,"cD":{"xY":3},"zz":4}

" Optionally upper case first letter too
zcl_ajson=>parse( '{"aj_bc":1}'
)->map( zcl_ajson_mapping=>create_to_camel_case(
iv_first_json_upper = abap_true ) ).
" {"AjBc":1}

All the above examples will also work with static create_from() method (but don't prefer it, might be deprecated).

zcl_ajson=>create_from(
ii_source_json = zcl_ajson=>parse( '{"aj_bc":1}' )
ii_mapper = zcl_ajson_mapping=>create_to_camel_case( )
).
" {"ajBc":1}

Mapping via to_abap and to_json (DEPRECATED)

This approach is depreciated and will be removed in future versions, please use rename_field approach described above

The interface zif_ajson_mapping allows to create custom mapping for ABAP and JSON fields via implementing to_abap and to_json methods.

Some mappings are provided by default:

  • ABAP ⇆ JSON mapping fields
  • JSON formatting to Camel Case
  • JSON formatting to UPPER/lower case

Example: JSON => ABAP mapping fields

JSON Input

{"field":"value","json.field":"field_value"}

Example code snippet

  data:
lo_ajson type ref to zcl_ajson,
li_mapping type ref to zif_ajson_mapping,
lt_mapping_fields type zif_ajson_mapping=>ty_mapping_fields,
ls_mapping_field like line of lt_mapping_fields.
data:
begin of ls_result,
abap_field type string,
field type string,
end of ls_result.

clear ls_mapping_field.
ls_mapping_field-abap = 'ABAP_FIELD'.
ls_mapping_field-json = 'json.field'.
insert ls_mapping_field into table lt_mapping_fields.

li_mapping = zcl_ajson_mapping=>create_field_mapping( lt_mapping_fields ).

lo_ajson =
zcl_ajson=>parse( iv_json = '{"field":"value","json.field":"field_value"}' ii_custom_mapping = li_mapping ).

lo_ajson->to_abap( importing ev_container = ls_result ).

Example: ABAP => JSON mapping fields

Example code snippet

  data:
lo_ajson type ref to zcl_ajson,
li_mapping type ref to zif_ajson_mapping,
lt_mapping_fields type zif_ajson_mapping=>ty_mapping_fields,
ls_mapping_field like line of lt_mapping_fields.
data:
begin of ls_result,
abap_field type string,
field type string,
end of ls_result.

clear ls_mapping_field.
ls_mapping_field-abap = 'ABAP_FIELD'.
ls_mapping_field-json = 'json.field'.
insert ls_mapping_field into table lt_mapping_fields.

li_mapping = zcl_ajson_mapping=>create_field_mapping( lt_mapping_fields ).

ls_result-abap_field = 'field_value'.
ls_result-field = 'value'.

lo_ajson = zcl_ajson=>create_empty( ii_custom_mapping = li_mapping ).

lo_ajson->set( iv_path = '/' iv_val = ls_result ).

JSON Output

{"field":"value","json.field":"field_value"}

Example: Camel Case - To JSON (first letter lower case)

Example code snippet

  data:
lo_ajson type ref to zcl_ajson,
li_mapping type ref to zif_ajson_mapping.
data:
begin of ls_result,
field_data type string,
end of ls_result.

li_mapping = zcl_ajson_mapping=>create_camel_case( iv_first_json_upper = abap_false ).

ls_result-field_data = 'field_value'.

lo_ajson = zcl_ajson=>create_empty( ii_custom_mapping = li_mapping ).

lo_ajson->set( iv_path = '/' iv_val = ls_result ).

JSON Output

{"fieldData":"field_value"}

Example: Camel Case - To JSON (first letter upper case)

Example code snippet

  data:
lo_ajson type ref to zcl_ajson,
li_mapping type ref to zif_ajson_mapping.
data:
begin of ls_result,
field_data type string,
end of ls_result.

li_mapping = zcl_ajson_mapping=>create_camel_case( iv_first_json_upper = abap_true ).

ls_result-field_data = 'field_value'.

lo_ajson = zcl_ajson=>create_empty( ii_custom_mapping = li_mapping ).

lo_ajson->set( iv_path = '/' iv_val = ls_result ).

JSON Output

{"FieldData":"field_value"}

Example: Camel Case - To ABAP

JSON Input

{"FieldData":"field_value"}

Example code snippet

  data:
lo_ajson type ref to zcl_ajson,
li_mapping type ref to zif_ajson_mapping.
data:
begin of ls_result,
field_data type string,
end of ls_result.

li_mapping = zcl_ajson_mapping=>create_camel_case( ).

lo_ajson = zcl_ajson=>parse( iv_json = '{"FieldData":"field_value"}' ii_custom_mapping = li_mapping ).

lo_ajson->to_abap( importing ev_container = ls_result ).

Example: Lower Case - To JSON

Example code snippet

  data:
lo_ajson type ref to zcl_ajson,
li_mapping type ref to zif_ajson_mapping.
data:
begin of ls_result,
field_data type string,
end of ls_result.

li_mapping = zcl_ajson_mapping=>create_lower_case( ).

ls_result-field_data = 'field_value'.

lo_ajson = zcl_ajson=>create_empty( ii_custom_mapping = li_mapping ).

lo_ajson->set( iv_path = '/' iv_val = ls_result ).

JSON Output

{"field_data":"field_value"}

Example: Upper Case - To JSON

Example code snippet

  data:
lo_ajson type ref to zcl_ajson,
li_mapping type ref to zif_ajson_mapping.
data:
begin of ls_result,
field_data type string,
end of ls_result.

li_mapping = zcl_ajson_mapping=>create_upper_case( ).

ls_result-field_data = 'field_value'.

lo_ajson = zcl_ajson=>create_empty( ii_custom_mapping = li_mapping ).

lo_ajson->set( iv_path = '/' iv_val = ls_result ).

JSON Output

{"FIELD_DATA":"field_value"}