Обновленный ответ:
В комментарии вы сказали:
порядок параметров запроса действительно не имеет значения, но переменные пути различны для разных путей (поэтому невозможно просто взять идентификатор и код - я предполагаю, что необходимо использовать регулярное выражение или сопоставление строк)
Да, вы можете извлечь биты в []
из путь и используйте их, помня для дальнейшего, что вы не хотите, чтобы они были в строке запроса:
function buildPath(path, params) {
const used = new Set();
// Replace the parts in [xxx]
path = path.replace(/\[([^\]]+)]/g, (m, c0) => {
used.add(c0);
return c0 in params ? params[c0] : "";
});
// Add query string if there are any left over
let qstr = Object.entries(params)
.filter(([key]) => !used.has(key))
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join("&");
return path + (qstr && "?" + qstr);
}
Live Пример:
function buildPath(path, params) {
const used = new Set();
// Replace the parts in [xxx]
path = path.replace(/\[([^\]]+)]/g, (m, c0) => {
used.add(c0);
return c0 in params ? params[c0] : "";
});
// Add query string if there are any left over
let qstr = Object.entries(params)
.filter(([key]) => !used.has(key))
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join("&");
return path + (qstr && "?" + qstr);
}
console.log("Your example:");
console.log(buildPath("/test/[id]/[code]/path", {id: 1, first: 'xyz', second: 2, code: 'abc'}));
console.log("Example without any query string:");
console.log(buildPath("/test/[id]/[code]/path", {id: 1, code: 'abc'}));
console.log("Your example with `first` and `second` reversed:");
console.log(buildPath("/test/[id]/[code]/path", {id: 1, second: 2, first: 'xyz', code: 'abc'}));
console.log("An example requiring URI encoding:");
console.log(buildPath("/test/[id]/[code]/path", {id: 1, blah: "value with & that needs encoding", code: 'abc'}));
.as-console-wrapper {
max-height: 100% !important;
}
Если вам нужно поддерживать значения массива, см. Второй блок кода ниже; Вы можете адаптировать его, чтобы добавить к вышеперечисленному.
Если вам нужно поддерживать устаревшие среды, которые не имеют Set
и не хотят использовать полифилл, вы можете использовать объект для отслеживания вместо используемых ключей:
// ES5 version
function buildPath(path, params) {
var used = Object.create(null); // So it doesn't inherit from Object.prototype and have "toString", etc.
// Replace the parts in [xxx]
path = path.replace(/\[([^\]]+)]/g, function(m, c0) {
used[c0] = true;
return c0 in params ? params[c0] : "";
});
// Add query string if there are any left over
let qstr = Object.keys(params)
.filter(function(key) { return !used[key]; })
.map(function(key) {
return encodeURIComponent(key) + "=" + encodeURIComponent(params[key]);
})
.join("&");
return path + (qstr && "?" + qstr);
}
console.log("Your example:");
console.log(buildPath("/test/[id]/[code]/path", {id: 1, first: 'xyz', second: 2, code: 'abc'}));
console.log("Example without any query string:");
console.log(buildPath("/test/[id]/[code]/path", {id: 1, code: 'abc'}));
console.log("Your example with `first` and `second` reversed:");
console.log(buildPath("/test/[id]/[code]/path", {id: 1, second: 2, first: 'xyz', code: 'abc'}));
console.log("An example requiring URI encoding:");
console.log(buildPath("/test/[id]/[code]/path", {id: 1, blah: "value with & that needs encoding", code: 'abc'}));
.as-console-wrapper {
max-height: 100% !important;
}
Оригинальный ответ:
Если порядок параметров запроса не имеет значения (или если объект всегда создается одинаково, и порядок добавления к нему свойств соответствует порядку, который вы хотите использовать в параметрах запроса), вы можете получить id
и code
от объекта и захватить все остальное для построения Строка запроса, что-то вроде этого:
function buildPath(path, params) {
const {id, code, ...query} = params;
return path.replace(/\[id]/, id)
.replace(/\[code]/, code) +
"?" +
Object.entries(query).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join("&");
}
// Your example
console.log(buildPath("/test/[id]/[code]/path", {id: 1, first: 'xyz', second: 2, code: 'abc'}));
// Your example with `first` and `second` reversed:
console.log(buildPath("/test/[id]/[code]/path", {id: 1, second: 2, first: 'xyz', code: 'abc'}));
// An example requiring URI encoding
console.log(buildPath("/test/[id]/[code]/path", {id: 1, blah: "value with & that needs encoding", code: 'abc'}));
Опять же, обратите внимание, что порядок параметров строки запроса (в современном браузере) будет соответствовать порядку, в котором свойства были созданы для объекта (обратите внимание на разницу между первые два примера выше). Однако для параметров с разными ключами это обычно не имеет значения для сервера.
Это также предполагает, что у вас никогда не будет массивов в качестве значений, которые вы хотите отправить в виде повторяющихся параметров запроса. Например, он отправляет:
{id: 1, code: 'abc', blah: ["one", "two", "three"]}
как /test/1/abc/path?blah=one%2Ctwo%2Cthree
. В некоторых средах вы хотите повторить имя параметра запроса blah
. Если это так, вам нужно обнаружить массив и обработать его:
function buildPath(path, params) {
const {id, code, ...query} = params;
const qstr = Object.entries(query).map(([key, value]) => {
key = encodeURIComponent(key) + "[]";
if (Array.isArray(value)) {
value = value.map(e => encodeURIComponent(e)).join(`&${key}=`);
} else {
value = encodeURIComponent(value);
}
return `${key}=${value}`;
}).join("&");
return path.replace(/\[id]/, id)
.replace(/\[code]/, code) +
qstr;
}
// Your example
console.log(buildPath("/test/[id]/[code]/path", {id: 1, first: 'xyz', second: 2, code: 'abc'}));
// Your example with `first` and `second` reversed:
console.log(buildPath("/test/[id]/[code]/path", {id: 1, second: 2, first: 'xyz', code: 'abc'}));
// An example requiring URI encoding
console.log(buildPath("/test/[id]/[code]/path", {id: 1, blah: "value with & that needs encoding", code: 'abc'}));
// An example with an array converted to repeated query params
console.log(buildPath("/test/[id]/[code]/path", {id: 1, code: 'abc', blah: ["one", "two", "three"]}));
Некоторые среды хотят видеть []
после клавиши, когда она используется таким образом. Если это так, просто измените
key = encodeURIComponent(key);
на
key = encodeURIComponent(key) + "[]";
в обратном вызове map
.