diff --git a/src/main/java/com/eactive/eai/message/parser/JsonReader.java b/src/main/java/com/eactive/eai/message/parser/JsonReader.java index a75e2a6..a8dfc47 100644 --- a/src/main/java/com/eactive/eai/message/parser/JsonReader.java +++ b/src/main/java/com/eactive/eai/message/parser/JsonReader.java @@ -119,8 +119,21 @@ public class JsonReader implements StandardReader { switch(currentNode.getNodeType()) { case OBJECT: - if( currentItem != null && currentItem.getSize() == 0 - && StringUtils.isNotBlank(currentItem.getRefPath()) + // refPath/refValue 는 "이 블록이 전문에 들어있는가" 를 판단하기 위한 조건이다. + // 고정길이(FLAT)는 블록의 존재를 알려주는 키가 없어 이 조건이 유일한 근거지만, + // JSON 은 키의 존재 자체가 답이다. 여기에 도달했다는 것은 수신 전문에 이 블록이 + // 실제로 들어있다는 뜻이므로, 조건으로 다시 걸러내면 받은 데이터를 잃는다. + // + // 실제 사고(2026-09): 상대가 오류응답을 procs_rslt_dvcd=F 로 보내면서 요청응답구분 + // dman_rspn_dvcd 는 요청값 S 를 그대로 에코백했다(표준은 응답 시 R). MSG 블록의 + // 조건이 !S 라 MSG 이하가 통째로 버려졌고, 그 결과 + // - MAIN_MSG 가 레이아웃 기본값으로 남아 오류가 "정상처리되었습니다." 로 보고되고 + // - 거래로그는 StandardMessage 재직렬화본이라 MSG 부 이후가 통째로 누락됐다. + // + // 조건 불일치는 상대 헤더의 오류로 보고, 경고만 남기고 파싱은 계속한다. + // (FlatReader 는 조건이 존재 판단에 반드시 필요하므로 그대로 둔다.) + if( currentItem != null && currentItem.getSize() == 0 + && StringUtils.isNotBlank(currentItem.getRefPath()) && StringUtils.isNotBlank(currentItem.getRefValue()) ) { String refItemValue = itemMap.get(currentItem.getRefPath()); @@ -131,25 +144,20 @@ public class JsonReader implements StandardReader { if (refItemValue != null) refItemValue = refItemValue.trim(); String refValue = currentItem.getRefValue(); - if (refValue.startsWith("!")) { // 느낌표가 들어가면 다음에 나오는게 아닌경우 + boolean negate = refValue.startsWith("!"); // 느낌표가 들어가면 다음에 나오는게 아닌경우 + if (negate) { refValue = refValue.substring(1); - if (refValue.equals(refItemValue)) { - logger.warn("@GROUP name={} SKIPPED.", currentItem.getName()); - currentItem.setHidden(true); - break; - } else { - currentItem.setHidden(false); - } - } else { - if (!currentItem.getRefValue().equals(refItemValue)) { - if (logger.isDebugEnabled()) - logger.warn("@GROUP name={} SKIPPED.", currentItem.getName()); - currentItem.setHidden(true); - break; - } else { - currentItem.setHidden(false); - } } + boolean matched = refValue.equals(refItemValue); + if (negate) { + matched = !matched; + } + if (!matched) { + logger.warn("@GROUP name={} 조건 불일치({}=[{}], 기대=[{}]). 수신 전문에 존재하므로 파싱은 계속한다.", + currentItem.getName(), currentItem.getRefPath(), refItemValue, + currentItem.getRefValue()); + } + currentItem.setHidden(false); } Iterator fieldNames = currentNode.fieldNames(); while(fieldNames.hasNext()) {