-
ABAP 동적 JSON 처리 - LCL_JSON_HANDLER 로컬 클래스 설계SAP/소스 2026. 7. 7. 21:27abap_json_handler.pdf0.09MBabap_json_handler.html0.02MB
ABAP 동적 JSON 처리 - LCL_JSON_HANDLER 로컬 클래스 설계 ABAP 동적 JSON 처리: LCL_JSON_HANDLER 로컬 클래스 설계
SAP ABAP 환경에서 JSON String을 동적 구조(REF TO DATA)로 변환하고, 구조체를 JSON으로 직렬화하는 로직을
/ui2/cl_json기반으로 모듈화한 과정을 정리한다. 펑션 그룹/리포트 양쪽에서 재사용 가능한 로컬 클래스, 인스턴스 기반 구조로 설계했다.1. 요구사항 정리
- 동적 데이터 전달 방식으로 JSON을 채택
- 값 변환은
/ui2/cl_json표준 클래스 사용 - JSON String → 동적 구조 변환 시
REF TO DATA타입으로 리턴 - 구조체 → JSON 변환은 직접 매핑 방식
- 각 로직은 class method로 모듈화
- 클래스는 로컬로 작성하여 펑션/리포트 어디서든 INCLUDE 가능하게, 인스턴스로 생성해 활용
2. 설계 원칙
JSON → ABAP은 타입을 모르는 상태에서 출발하므로
/ui2/cl_json=>generate()로 런타임에 타입을 결정해REF TO DATA를 생성한다. 반대로 ABAP → JSON은 이미 정의된 구조체를 그대로 직렬화(serialize())하면 되므로 별도의 동적 타입 판별이 필요 없다.💡 struc → itab → field 계층 구조를 다룰 때는cl_abap_typedescr=>describe_by_data()로 얻은kind값(kind_elem / kind_struct / kind_table)을 기준으로 재귀 순회하는 것이 기본 패턴이다. 다만/ui2/cl_json=>generate()를 쓰면 이 재귀 타입 생성 과정을 라이브러리가 대신 처리해준다.3. 최종 소스: LCL_JSON_HANDLER (로컬 클래스, 인스턴스 기반)
펑션 그룹의
INCLUDE나 리포트 TOP-INCLUDE 어디에 넣어도 동작하도록 구성했다. 예외 클래스(lcx_json_error)와 결과 구조(ty_json_result)를 함께 정의하고,CREATE OBJECT로 인스턴스를 만들어 메소드를 호출하는 구조다.주요 메소드 구성
메소드 역할 json_to_dynamic_data JSON String → REF TO DATA (동적 구조 생성) struc_to_json 구조체(정적 타입) → JSON String 직렬화 get_field_value 동적 데이터에서 특정 필드값 조회 get_type_kind REF TO DATA의 TYPE KIND(elem/struct/table) 판별 is_valid_json JSON 형식 간단 유효성 체크 convert_with_error_handling 변환+예외처리를 하나로 묶은 통합 래퍼 ⚠️ nested itab(구조 안에 배열이 중첩된 경우) 내부 라인 순회 로직(get_table_lines등)은 아직 포함되지 않았다. 실제 JSON에 배열 중첩이 있다면 RTTI 재귀 로직을 별도로 추가해야 한다.체크리스트
- naming 매핑(camelCase vs none) 확인 후 constructor 파라미터로 지정
- 날짜/시간 필드 포맷(JSON 문자열 ↔ DATS/TIMS) 사전 확인
- 대량 데이터 처리 시 RTTI/동적 ASSIGN 성능 저하 고려
- 순환 참조/과도한 nested 구조에 대한 재귀 깊이 제한 필요 여부 검토
4. 전체 소스 코드
*&---------------------------------------------------------------------* *& LCL_JSON_HANDLER *& - JSON String -> 동적 구조(REF TO DATA) 변환 *& - 구조체/테이블 -> JSON String 변환 *& - RTTI 기반 동적 필드 접근 유틸 *& * 리포트 TOP-INCLUDE 또는 함수그룹 LCL_INCLUDE 어디든 삽입 가능 *&---------------------------------------------------------------------* "---------------------------------------------------------------------- " 예외 클래스 (로컬) "---------------------------------------------------------------------- CLASS lcx_json_error DEFINITION INHERITING FROM cx_static_check. PUBLIC SECTION. DATA mv_msg TYPE string. METHODS constructor IMPORTING iv_msg TYPE string OPTIONAL previous LIKE previous OPTIONAL. ENDCLASS. CLASS lcx_json_error IMPLEMENTATION. METHOD constructor. super->constructor( previous = previous ). mv_msg = iv_msg. ENDMETHOD. ENDCLASS. "---------------------------------------------------------------------- " 결과 구조 (변환 결과 공통 리턴 타입) "---------------------------------------------------------------------- TYPES: BEGIN OF ty_json_result, success TYPE abap_bool, message TYPE string, data TYPE REF TO data, END OF ty_json_result. "---------------------------------------------------------------------- " LCL_JSON_HANDLER 클래스 정의 "---------------------------------------------------------------------- CLASS lcl_json_handler DEFINITION. PUBLIC SECTION. "---------------------------------------------------- " 생성자 : 기본 Naming 모드 설정 (camelCase / none 등) "---------------------------------------------------- METHODS constructor IMPORTING iv_pretty_name TYPE /ui2/cl_json=>pretty_name_mode DEFAULT /ui2/cl_json=>pretty_mode-camel_case. "---------------------------------------------------- " ① JSON String -> 동적 구조 (REF TO DATA) "---------------------------------------------------- METHODS json_to_dynamic_data IMPORTING iv_json TYPE string RETURNING VALUE(rr_data) TYPE REF TO data RAISING lcx_json_error. "---------------------------------------------------- " ② 구조체(정적 타입) -> JSON String "---------------------------------------------------- METHODS struc_to_json IMPORTING is_data TYPE any iv_compress TYPE abap_bool DEFAULT abap_true RETURNING VALUE(rv_json) TYPE string. "---------------------------------------------------- " ③ 동적 데이터 내 특정 필드값 조회 (Structure 전제) "---------------------------------------------------- METHODS get_field_value IMPORTING ir_data TYPE REF TO data iv_fieldname TYPE string RETURNING VALUE(rv_value) TYPE string RAISING lcx_json_error. "---------------------------------------------------- " ④ 동적 데이터의 TYPE KIND 판별 (elem/struct/table) "---------------------------------------------------- METHODS get_type_kind IMPORTING ir_data TYPE REF TO data RETURNING VALUE(rv_kind) TYPE abap_typekind. "---------------------------------------------------- " ⑤ JSON 유효성 간단 체크 "---------------------------------------------------- METHODS is_valid_json IMPORTING iv_json TYPE string RETURNING VALUE(rv_valid) TYPE abap_bool. "---------------------------------------------------- " ⑥ 에러 핸들링 통합 래퍼 (호출부는 이 메소드 하나만 써도 됨) "---------------------------------------------------- METHODS convert_with_error_handling IMPORTING iv_json TYPE string RETURNING VALUE(rs_result) TYPE ty_json_result. PRIVATE SECTION. DATA mv_pretty_name TYPE /ui2/cl_json=>pretty_name_mode. ENDCLASS. "---------------------------------------------------------------------- " LCL_JSON_HANDLER 구현 "---------------------------------------------------------------------- CLASS lcl_json_handler IMPLEMENTATION. METHOD constructor. mv_pretty_name = iv_pretty_name. ENDMETHOD. METHOD json_to_dynamic_data. IF me->is_valid_json( iv_json ) = abap_false. RAISE EXCEPTION TYPE lcx_json_error EXPORTING iv_msg = |Invalid JSON string|. ENDIF. TRY. /ui2/cl_json=>generate( EXPORTING json = iv_json pretty_name = mv_pretty_name RECEIVING r_value = rr_data ). CATCH cx_root INTO DATA(lx_error). RAISE EXCEPTION TYPE lcx_json_error EXPORTING iv_msg = |JSON generate failed: { lx_error->get_text( ) }| previous = lx_error. ENDTRY. IF rr_data IS NOT BOUND. RAISE EXCEPTION TYPE lcx_json_error EXPORTING iv_msg = |JSON conversion returned no data|. ENDIF. ENDMETHOD. METHOD struc_to_json. rv_json = /ui2/cl_json=>serialize( data = is_data pretty_name = mv_pretty_name compress = iv_compress ). ENDMETHOD. METHOD get_type_kind. DATA(lo_type) = cl_abap_typedescr=>describe_by_data_ref( ir_data ). rv_kind = lo_type->type_kind. ENDMETHOD. METHOD get_field_value. FIELD-SYMBOLS: <fs_struc> TYPE any, <fs_field> TYPE any. ASSIGN ir_data->* TO <fs_struc>. IF sy-subrc <> 0. RAISE EXCEPTION TYPE lcx_json_error EXPORTING iv_msg = |Dereference failed|. ENDIF. ASSIGN COMPONENT iv_fieldname OF STRUCTURE <fs_struc> TO <fs_field>. IF sy-subrc <> 0. RAISE EXCEPTION TYPE lcx_json_error EXPORTING iv_msg = |Field { iv_fieldname } not found|. ENDIF. rv_value = <fs_field>. ENDMETHOD. METHOD is_valid_json. rv_valid = abap_true. IF iv_json IS INITIAL. rv_valid = abap_false. RETURN. ENDIF. DATA(lv_trim) = condense( iv_json ). IF NOT ( lv_trim(1) = '{' OR lv_trim(1) = '[' ). rv_valid = abap_false. ENDIF. ENDMETHOD. METHOD convert_with_error_handling. TRY. rs_result-data = me->json_to_dynamic_data( iv_json ). rs_result-success = abap_true. rs_result-message = |Conversion successful|. CATCH lcx_json_error INTO DATA(lx_error). rs_result-success = abap_false. rs_result-message = lx_error->mv_msg. ENDTRY. ENDMETHOD. ENDCLASS. "---------------------------------------------------------------------- " 호출부 사용 예시 (인스턴스 생성) "---------------------------------------------------------------------- DATA: lo_json TYPE REF TO lcl_json_handler. CREATE OBJECT lo_json EXPORTING iv_pretty_name = /ui2/cl_json=>pretty_mode-camel_case. "--- JSON -> 동적 구조 --- TRY. DATA(lr_dynamic) = lo_json->json_to_dynamic_data( '{"orderId":"1000","amount":250.5}' ). FIELD-SYMBOLS <fs> TYPE any. ASSIGN lr_dynamic->* TO <fs>. CATCH lcx_json_error INTO DATA(lx_err). WRITE: / lx_err->mv_msg. ENDTRY. "--- 구조체 -> JSON --- TYPES: BEGIN OF ty_order, order_id TYPE string, amount TYPE p DECIMALS 2, END OF ty_order. DATA(ls_order) = VALUE ty_order( order_id = '1000' amount = '250.50' ). DATA(lv_json) = lo_json->struc_to_json( ls_order ). "--- 통합 에러핸들링 래퍼 사용 --- DATA(ls_result) = lo_json->convert_with_error_handling( '{"a":1}' ). IF ls_result-success = abap_true. " ls_result-data 사용 ELSE. " ls_result-message 로 에러 처리 ENDIF.'SAP > 소스' 카테고리의 다른 글
ABAP Nugget Viewer (0) 2026.06.04 Z_MYBATIS_TO_ABAP — 설계 및 설치 가이드 (0) 2026.05.27 ABAP — HTML/XML 속성값 추출 패턴 (0) 2026.05.27 AMDP SQLScript 날짜·시간 계산 함수 예제 (0) 2026.05.25 ABAP PascalCase 변환 — snake_case ↔ Table Field (0) 2026.05.19