diff --git a/src/main/java/com/sb/web/account/service/AiEntryParser.java b/src/main/java/com/sb/web/account/service/AiEntryParser.java index 42fabe1..428cbd4 100644 --- a/src/main/java/com/sb/web/account/service/AiEntryParser.java +++ b/src/main/java/com/sb/web/account/service/AiEntryParser.java @@ -86,7 +86,13 @@ public class AiEntryParser { String out = stripFences(resp.path("content").path(0).path("text").asText("")).trim(); log.info("[ai-parse] 모델 원문='{}'", out); - JsonNode j = om.readTree(out); + // 모델이 설명문을 섞어 보내도 첫 '{'~마지막 '}' 만 추출해 JSON 파싱(견고성). + String json = extractJson(out); + if (json == null) { + log.info("[ai-parse] JSON 없음 — 거래 아님으로 간주, 규칙기반 폴백"); + return Optional.empty(); + } + JsonNode j = om.readTree(json); String type = "INCOME".equalsIgnoreCase(j.path("type").asText("EXPENSE")) ? "INCOME" : "EXPENSE"; LocalDate date; @@ -111,6 +117,14 @@ public class AiEntryParser { } } + /** 설명문이 앞뒤로 붙어도 첫 '{'~마지막 '}' 구간만 잘라 JSON 만 추출. 중괄호 없으면 null. */ + private String extractJson(String s) { + int a = s.indexOf('{'); + int b = s.lastIndexOf('}'); + if (a >= 0 && b > a) return s.substring(a, b + 1); + return null; + } + /** 모델이 ```json ... ``` 로 감쌌을 때 코드펜스 제거. */ private String stripFences(String s) { String t = s.trim();