Вы можете перезаписать .getJSON
собственным методом.
Родной getJSON
метод можно увидеть здесь:
https://j11y.io/jquery/#v=git&fn=jQuery.getJSON
function (url, data, callback) {
return jQuery.get(url, data, callback, "json");
}
Достаточно просто принять ответный вызов, переданный на getJSON
, передать свой собственный обратный вызов на jQuery.get
с 'text'
вместо 'json'
, проанализировать JSON с помощью пользовательского reviver, и затем вызовите исходный обратный вызов.
Сложность заключается в том, что второй параметр, переданный в getJSON
, является необязательным (данные для отправки вместе с запросом).
Предполагая, что вы всегда используете функцию успеха (третий и последний аргумент), вы можете использовать остальные параметры и pop()
, чтобы получить переданную функцию успеха. Создайте пользовательскую функцию успеха, которая принимает текстовый ответ и использует пользовательский JSON.parse
, а затем вызывает переданную функцию успеха с созданным объектом.
const dequoteDigits = json => JSON.parse(
json,
(key, val) => (
typeof val === 'string' && /^[+-]?[0-9]+(?:\.[0-9]+)$/.test(val)
? Number(val)
: val
)
);
jQuery.getJSON = function (url, ...rest) {
// normal parameters: url, data (optional), success
const success = rest.pop();
const customSuccess = function(textResponse, status, jqXHR) {
const obj = dequoteDigits(textResponse);
success.call(this, obj, status, jqXHR);
};
// spread the possibly-empty empty array "rest" to put "data" into argument list
return jQuery.get(url, ...rest, customSuccess, 'text');
};
jQuery.getJSON('https://jsonplaceholder.typicode.com/users', (obj) => {
console.log(obj);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Разница в выводе фрагмента выше по сравнению с запрошенным URL
https://jsonplaceholder.typicode.com/users
означает, что значения свойств широты и долготы были преобразованы в числа, а не в оставшиеся строки.
Если вы когда-либо используете await
также без обратного вызова, то вам нужно перезаписать свойство then
возвращенного Promise, хотя работа с необязательным обратным вызовом успеха делает логику кода намного более уродливой:
const dequoteDigits = json => JSON.parse(
json,
(key, val) => (
typeof val === 'string' && /^[+-]?[0-9]+(?:\.[0-9]+)$/.test(val)
? Number(val)
: val
)
);
jQuery.getJSON = function (url, ...rest) {
// normal parameters: url, data (optional), success (optional)
const data = rest.length && typeof rest[0] !== 'function'
? [rest.shift()]
: [];
const newSuccessArr = typeof rest[0] === 'function'
? [function(textResponse, status, jqXHR) {
const obj = dequoteDigits(textResponse);
rest[0].call(this, obj, status, jqXHR);
}
]
: [];
// spread the possibly-empty dataObj and newSuccessObj into the new argument list array
const newArgs = [url, ...data, ...newSuccessArr, 'text'];
const prom = jQuery.get.apply(this, newArgs);
const nativeThen = prom.then;
prom.then = function(resolve) {
nativeThen.call(this)
.then((res) => {
const obj = dequoteDigits(this.responseText);
resolve(obj);
});
};
return prom;
};
jQuery.getJSON('https://jsonplaceholder.typicode.com/users', (obj) => {
console.log(obj[0].address.geo);
});
(async () => {
const obj = await jQuery.getJSON('https://jsonplaceholder.typicode.com/users');
console.log(obj[0].address.geo);
// console.log(obj);
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>