
프로젝트에서 Vue로 데이터 연동을 시도하던 중 발생한 문제
그래서 하나하나 뜯어보며 확인했다.
기본적인 구조는 다음과 같다.
try {
const response = await this.$dApi.$get('/api/data/setting', { mode: 'cors' });
const parsedResponse = JSON.parse(response.data);
// 전체 데이터 확인
// console.log("Full response:", parsedResponse);
// 응답 타입 확인
// console.log("Response type:", typeof parsedResponse);
// 응답 구조 상세 확인
// console.log("Response keys:", Object.keys(parsedResponse));
this.responeseData = parsedResponse;
this.SeasonData = cleanedResponse.merge_tariff_tou || [];
this.PriceData = parsedResponse.merge_tariff_tou || [];
this.PlaceData = parsedResponse.site_info || [];
this.RangeData = parsedResponse.merge_tariff_tou || [];
this.energyData = parsedResponse.merge_energy_resource || [];
this.activeData = parsedResponse.active_resource || [];
this.batteryData = parsedResponse.battery_resource || [];
this.sitePeak = (parsedResponse.site_info && parsedResponse.site_info[0] && parsedResponse.site_info[0].load_peak) || null;
} catch (error) {
console.error("Error while fetching data:", error);
}
에러가 났던 이유는 JS에서 NaN 처리를 할 수 없던 것!
그래서 나는 NaN일 경우 후처리를 하는 로직을 추가!
async mounted() {
try {
const response = await this.$dApi.$get('/api/data/setting', { mode: 'cors' });
let responseStr = response;
console.log("check data : ", responseStr)
if (typeof responseStr === 'string') {
responseStr = responseStr.replace(/NaN/g, 'null');
}
const parsedResponse = JSON.parse(responseStr);
const replaceNaNWithNull = (obj) => {
if (obj === null || obj === undefined) return obj;
if (typeof obj === 'number' && isNaN(obj)) {
return null;
}
if (Array.isArray(obj)) {
return obj.map(replaceNaNWithNull);
}
if (typeof obj === 'object') {
return Object.fromEntries(
Object.entries(obj).map(([key, value]) => [key, replaceNaNWithNull(value)])
);
}
return obj;
};
const cleanedResponse = replaceNaNWithNull(parsedResponse);
// 전체 데이터 확인
// console.log("Full response:", cleanedResponse);
// 응답 타입 확인
// console.log("Response type:", typeof cleanedResponse);
// 응답 구조 상세 확인
// console.log("Response keys:", Object.keys(cleanedResponse));
this.responeseData = cleanedResponse;
this.SeasonData = cleanedResponse.merge_tariff_tou || [];
this.PriceData = cleanedResponse.merge_tariff_tou || [];
this.PlaceData = cleanedResponse.site_info || [];
this.RangeData = cleanedResponse.merge_tariff_tou || [];
this.energyData = cleanedResponse.merge_energy_resource || [];
this.activeData = cleanedResponse.active_resource || [];
this.batteryData = cleanedResponse.battery_resource || [];
this.sitePeak = (cleanedResponse.site_info && cleanedResponse.site_info[0] && cleanedResponse.site_info[0].load_peak) || null;
} catch (error) {
console.error("Error while fetching data:", error);
}
방법은 간단하다.
우선 Get으로 받아온 데이터를 Pasing을 하되 그 데이터를 Function을 거쳐 후처리를 하는 것.
어렵지 않다. 우선 null인지 undefind인지 확인하고 맞을 경우 return을 한다.
그걸 확인하기 위해 데이터 구조를 파악하고, 배열 혹은 객체일 경우 전체 데이터를 map을 통해 재귀로 모든 데이터의 NaN 값을 null로 바꿔주기로 하였다.
위 처럼 하다보니 이거 그냥 함수 만들어야겠는데? 생각이 들었고
const replaceNaNWithNull = (obj) => {
if (typeof obj === 'string') {
obj = obj.replace(/NaN/g, 'null'); // 문자열에서 NaN을 null로 대체
}
if (obj === null || obj === undefined) return obj;
if (typeof obj === 'number' && isNaN(obj)) {
return null;
}
if (Array.isArray(obj)) {
return obj.map(replaceNaNWithNull);
}
if (typeof obj === 'object') {
return Object.fromEntries(
Object.entries(obj).map(([key, value]) => [key, replaceNaNWithNull(value)])
);
}
return obj;
};
try {
const response = await this.$dApi.$get('/api/data/setting', { mode: 'cors' });
let responseStr = response;
console.log("check data : ", responseStr);
if (typeof responseStr === 'string') {
responseStr = responseStr.replace(/NaN/g, 'null');
}
const parsedResponse = JSON.parse(responseStr);
const cleanedResponse = replaceNaNWithNull(parsedResponse);
// cleanedResponse 사용
this.responeseData = cleanedResponse;
this.SeasonData = cleanedResponse.merge_tariff_tou || [];
this.PriceData = cleanedResponse.merge_tariff_tou || [];
this.PlaceData = cleanedResponse.site_info || [];
this.RangeData = cleanedResponse.merge_tariff_tou || [];
this.energyData = cleanedResponse.merge_energy_resource || [];
this.activeData = cleanedResponse.active_resource || [];
this.batteryData = cleanedResponse.battery_resource || [];
this.sitePeak = (cleanedResponse.site_info && cleanedResponse.site_info[0] && cleanedResponse.site_info[0].load_peak) || null;
} catch (error) {
console.error(error);
}
}
위 처럼 바꿨는데 기본적으로 typeof가 string일 때 처음은 처리해둬야 정상적으로 받아집니다..
근데 이건 내잘못이 맞는게 백엔드에서 처리하고 보냈으면 깔끔했다... 그냥 그렇다고..
백엔드에서는 아래 처리를 해주면 된다..
result = {
"site_info": site_tariff_merged_df.to_dict(orient="records"),
"merge_tariff_tou": tariff_tou_merged_df.to_dict(orient="records"),
"merge_energy_resource": merged_resource_df.to_dict(orient="records"),
"battery_resource": battery_resource_df.to_dict(orient="records"),
"active_resource": active_resource_df.to_dict(orient="records"),
}
def replace_nan_with_none(obj):
if isinstance(obj, float) and math.isnan(obj):
return None
if isinstance(obj, dict): # dict 타입 처리
return {k: replace_nan_with_none(v) for k, v in obj.items()}
if isinstance(obj, list): # list 타입 처리
return [replace_nan_with_none(i) for i in obj]
return obj
# NaN을 None으로 변환
cleaned_result = replace_nan_with_none(result)
# Flask에서 JSON 응답 반환
return jsonify(cleaned_result)
뭐든 형변환만 해주면 상관없다!