API 응답 정규화
27260 단어 serializationexpressjavascriptnode
Note: All examples are using express v4 and body-parser.
const todos = [{ ... }, { ... }]; // an array of todos
router.get('/todos', function(req, res, next){
res.status(200);
res.json({
msg: 'So many things to do',
todos: todos,
});
});
router.post('/todos', function(req, res, next){
const todo = {
title: req.body.title,
description: req.body.description,
completed: false,
id: uuid(), // generate a random id,
};
try {
todos.push(todo); // imagine this might fail, todo is a remote db :)
} catch (e) {
return next(e);
}
res.status(201);
res.json({
message: 'Todo created',
data: todo,
});
});
위에서 각 엔드포인트에는 매우 유사한 구조가 주어진 응답에 대한 고유한 구조가 있음을 볼 수 있습니다. 둘 다 메시지와 데이터 세트를 다시 보내지만 다른 키를 사용합니다. 이 문제는 믹스에 오류를 던지기 시작할 때 더욱 분명해집니다.
API 응답 정규화
객체를 반환하는 함수를 만들어 이 문제를 해결할 수 있습니다. 단순화를 위해 이 개체에는 4개의 키 값 쌍이 있습니다.
function apiResponse(data = {}, status = 1, errors = [], message = '') {
return {
data,
status,
errors,
message,
};
}
좋은 시작이지만 동료 개발자는 매개변수의 순서를 생각해야 합니다. 개체를 매개변수로 받아들이고 필요한 키를 분해하여 문제를 해결해 보겠습니다.
function apiResponse({ data = {}, status = 1, errors = [], message = '' }) {
return {
data,
status,
errors,
message,
};
}
이 솔루션이 작동하는 동안 실수로부터 우리를 보호하지는 않습니다. 초기화 후 개체 구조의 무결성이 위험합니다. 더 많은 제어권을 얻을 수 있도록 apiResponse를 클래스로 바꾸겠습니다.
class ApiResponse {
constructor({ data = {}, status = 1, errors = [], message = '' }) {
this._data = data;
this._status = status;
this._errors = errors;
this._message = message;
}
}
내부적으로
res.json()
는 페이로드에서 JSON.stringify()
를 호출하여 인코딩합니다. stringify
의 멋진 측면 영향 중 하나는 개체에 값이 함수인 toJSON 속성이 있는 경우 해당 함수가 호출되어 개체가 직렬화되는 방식을 정의한다는 것입니다. 즉, JSON 문자열에 표시할 키를 선택할 수 있습니다.class ApiResponse {
constructor({ data = {}, status = 1, errors = [], message = '' }) {
this._data = data;
this._status = status;
this._errors = errors;
this._message = message;
}
toJSON() {
return {
data: this._data,
status: this._status,
errors: this._errors,
message: this._message,
};
}
}
안타깝게도 자바스크립트 클래스에는 개인 키가 없습니다. 우리가 가진 가장 가까운 것은
Symbols
입니다. 그것들을 사용하여 키를 "비공개"로 만들 수 있습니다.const apiResponse = (payload = {}) => {
const DataSymbol = Symbol('data');
const StatusSymbol = Symbol('status');
const ErrorsSymbol = Symbol('errors');
const MessageSymbol = Symbol('message');
class ApiResponse {
constructor({ data = {}, status = 1, errors = [], message = '' }) {
this[DataSymbol] = data;
this[StatusSymbol] = status;
this[ErrorsSymbol] = errors;
this[MessageSymbol] = message;
}
toJSON() {
return {
data: this[DataSymbol],
status: this[StatusSymbol],
errors: this[ErrorsSymbol],
message: this[MessageSymbol],
}
}
}
return new ApiResponse(payload);
}
Javascript에도 유형이 없지만
getters
및 setters
가 있습니다. 그것들을 사용하여 할당에 대한 유형 검사를 수행할 수 있습니다. 이것이 코드의 최종 진화입니다.const apiResponse = (payload = {}) => {
const DataSymbol = Symbol('data');
const StatusSymbol = Symbol('status');
const ErrorsSymbol = Symbol('errors');
const MessageSymbol = Symbol('message');
class ApiResponse {
constructor({ data = {}, status = 1, errors = [], message = '' }) {
this.data = data;
this.status = status;
this.errors = errors;
this.message = message;
}
get data() {
return this[DataSymbol];
}
set data(data) {
if (typeof data === 'undefined')
throw new Error('Data must be defined');
this[DataSymbol] = data;
}
get status() {
return this[StatusSymbol];
}
set status(status) {
if (isNaN(status) || (status !== 0 && status !== 1))
throw new Error('Status must be a number, 1 is OK, 0 is BAD');
this[StatusSymbol] = status;
}
get errors() {
return this[ErrorsSymbol];
}
set errors(errors) {
if (!Array.isArray(errors))
throw new Error('Errors must be an array');
this[ErrorsSymbol] = errors;
}
get message() {
return this[MessageSymbol];
}
set message(message) {
if (typeof message !== 'string')
throw new Error('Message must be a string');
this[MessageSymbol] = message;
}
toJSON() {
return {
data: this.data,
status: this.status,
errors: this.errors.map(e => e.stack ? e.stack : e),
message: this.message,
}
}
}
return new ApiResponse(payload);
}
게터와 세터는 초기화 후 응답 객체를 안전하게 변경할 수 있는 기능도 제공합니다. 이제 새로운
apiResponse
기능 🎉을 사용하여 재미있는 부분이 나옵니다!const todos = [{ ... }, { ... }]; // an array of todos
router.get('/todos', function(req, res, next){
res.status(200);
res.json(apiResponse({
data: todos,
message: 'You have a lot todo!',
}));
});
GET/todos에서 예상되는 응답
{
"data": [{ ... }, { ... }],
"message": "You have a lot todo!",
"errors": [],
"status": 1,
}
일단 그게 전부 야. 이것은 나의 첫 번째 게시물이며 귀하의 의견을 듣고 싶습니다. 이것이 누군가에게 도움이 되기를 바랍니다. 행복한 코딩!
Reference
이 문제에 관하여(API 응답 정규화), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/mattdevio/normalizing-api-responses-409m텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)