- 소수 자릿수 처리 개선 - DECIMAL/BIGDECIMAL 정수/숫자 구분
eapim-admin CI / build (push) Has been cancelled

- 샘플 생성 로직 리팩토링 - 길이 및 소수 자릿수 기준 상세화
- 공통 스키마 처리 함수 추가 - 코드 중복 제거 및 가독성 향상
This commit is contained in:
Rinjae
2026-08-13 14:42:44 +09:00
parent 760000070d
commit e364a35b66
4 changed files with 133 additions and 65 deletions
+34 -14
View File
@@ -224,6 +224,8 @@
const s = { type: row.type.value };
if (row.format && row.format.value) s.format = row.format.value;
if (row.maxLength && row.maxLength.value) s.maxLength = Number(row.maxLength.value);
// 소수 자릿수(GW 레이아웃 유래) 보존 — 예제값 생성 시 '.' 포함 길이 계산에 사용
if (row.decimals && row.decimals.value !== '' && row.decimals.value != null) s['x-djb-decimal'] = Number(row.decimals.value);
if (row.pattern && row.pattern.value) s.pattern = row.pattern.value;
if (row.description && row.description.value) s.description = row.description.value;
if (row.example && row.example.value !== '') s.example = coerceExample(row.type.value, row.example.value);
@@ -1466,6 +1468,7 @@
required: { value: false, locked: false },
format: { value: '', locked: false },
maxLength: { value: '', locked: false },
decimals: { value: '', locked: false },
pattern: { value: '', locked: false },
description: { value: '', locked: false },
example: { value: '', locked: false },
@@ -1480,6 +1483,7 @@
required: { value: false, locked: false },
format: { value: '', locked: false },
maxLength: { value: '', locked: false },
decimals: { value: '', locked: false },
pattern: { value: '', locked: false },
description: { value: '', locked: false },
example: { value: '', locked: false }
@@ -1733,6 +1737,7 @@
var row = {
name: wrap(name, gw), type: wrap(t, gw), required: wrap(!!required, false),
format: wrap(p.format || ''), maxLength: wrap(p.maxLength == null ? '' : p.maxLength),
decimals: wrap(p['x-djb-decimal'] == null ? '' : p['x-djb-decimal']),
pattern: wrap(p.pattern || ''), description: wrap(p.description || ''),
example: wrap(p.example == null ? '' : p.example), children: null
};
@@ -1782,7 +1787,7 @@
};
d.parameters = (op.parameters || []).map(function (p) {
var s = p.schema || {};
return { in: p.in || 'query', name: wrap(p.name), type: wrap(s.type || 'string'), required: wrap(!!p.required), format: wrap(s.format || ''), maxLength: wrap(s.maxLength == null ? '' : s.maxLength), pattern: wrap(s.pattern || ''), description: wrap(p.description || ''), example: wrap(p.example == null ? '' : p.example) };
return { in: p.in || 'query', name: wrap(p.name), type: wrap(s.type || 'string'), required: wrap(!!p.required), format: wrap(s.format || ''), maxLength: wrap(s.maxLength == null ? '' : s.maxLength), decimals: wrap(s['x-djb-decimal'] == null ? '' : s['x-djb-decimal']), pattern: wrap(s.pattern || ''), description: wrap(p.description || ''), example: wrap(p.example == null ? '' : p.example) };
});
var rb = op.requestBody || {}; var rbc = rb.content || {}; var mt = Object.keys(rbc)[0] || 'application/json';
d.requestBody = { mediaType: mt, required: wrap(!!rb.required), schema: schemaToRows((rbc[mt] || {}).schema) };
@@ -1827,19 +1832,34 @@
// 스키마 기반 샘플 JSON 생성 (자동생성 예제)
function _coerce(t, v) { if (t === 'integer') return parseInt(v, 10) || 0; if (t === 'number') return parseFloat(v) || 0; if (t === 'boolean') return v === true || v === 'true'; return v; }
// 기본 예제값: string→sample_명(길이 지정 시 맞춰 자름), integer→123456, number→123456.123, boolean→false
// - 숫자는 길이 지정 시 정수부를 그 길이에 맞춰 자름(실수는 소수 .123 유지)
function _defScalar(t, name, maxLen) {
var ml = parseInt(maxLen, 10);
if (t === 'integer') {
var iv = '123456';
if (ml && ml > 0 && iv.length > ml) iv = iv.substring(0, ml);
return parseInt(iv, 10);
// 자릿수 문자열: start 위치부터 1~9 를 순환('123456789123...')
function _digits(start, count) { var s = ''; for (var i = 0; i < count; i++) s += String(((start + i) % 9) + 1); return s; }
// 숫자 예제값. 길이는 소수점(.)까지 포함한 문자열 전체 길이로 계산한다.
// 예) 길이 9 / 소수 5 → 123.45678 (정수부 3 + '.' 1 + 소수부 5 = 9자)
// - 길이가 소수부+2 보다 짧으면 정수부 1자리를 확보하고 소수부를 줄인다.
// - 길이 미지정이면 정수부 6자리(기존 기본값)를 사용한다.
function _numSample(maxLen, dec) {
var ml = parseInt(maxLen, 10) || 0, d = parseInt(dec, 10) || 0;
if (d <= 0) return _digits(0, ml > 0 ? Math.min(ml, 6) : 6);
var il;
if (ml > 0) {
il = ml - d - 1;
if (il < 1) { il = 1; d = Math.max(1, ml - 2); }
} else {
il = 6;
}
return _digits(0, il) + '.' + _digits(il, d);
}
// 기본 예제값: string→sample_명(길이 지정 시 맞춰 자름), integer→123456, number→123.45678, boolean→false
// - 숫자는 지정 길이를 넘지 않도록 자릿수를 맞춘다(소수는 '.' 포함 길이 기준).
// - number 인데 소수 자릿수 정보가 없으면 3자리로 가정(소수 0자리는 백엔드가 integer 로 매핑).
function _defScalar(t, name, maxLen, decimals) {
var ml = parseInt(maxLen, 10);
if (t === 'integer') return parseInt(_numSample(ml, 0), 10);
if (t === 'number') {
var ip = '123456';
if (ml && ml > 0 && ip.length > ml) ip = ip.substring(0, ml);
return parseFloat(ip + '.123');
var d = parseInt(decimals, 10);
if (!(d > 0)) d = 3;
return parseFloat(_numSample(ml, d));
}
if (t === 'boolean') return false;
var v = 'sample_' + (name || '');
@@ -1851,7 +1871,7 @@
if (t === 'object') return _sampleObj(row.children || []);
if (t === 'array') { var it = (row.itemsType && row.itemsType.value) || 'string'; return [it === 'object' ? _sampleObj(row.children || []) : _defScalar(it, (row.name && row.name.value) || 'item', '')]; }
if (ex !== undefined && ex !== '') return _coerce(t, ex);
return _defScalar(t, (row.name && row.name.value) || '', row.maxLength && row.maxLength.value);
return _defScalar(t, (row.name && row.name.value) || '', row.maxLength && row.maxLength.value, row.decimals && row.decimals.value);
}
function _sampleObj(rows) { var o = {}; (rows || []).forEach(function (r) { if (r && r.name && r.name.value) o[r.name.value] = _sampleVal(r); }); return o; }
function ensureExamplesFromSchema(force) {
@@ -1897,7 +1917,7 @@
if (r.children && r.children.length) fillSchemaExamples(r.children);
} else {
r.example = r.example || { value: '', locked: false };
r.example.value = String(_defScalar(t, r.name.value || '', r.maxLength && r.maxLength.value));
r.example.value = String(_defScalar(t, r.name.value || '', r.maxLength && r.maxLength.value, r.decimals && r.decimals.value));
}
});
}