You can overwrite .getJSON
with your own method.
The native getJSON
method can be seen here:
https://j11y.io/jquery/#v=git&fn=jQuery.getJSON
function (url, data, callback) {
return jQuery.get(url, data, callback, "json");
}
It's a simple enough matter to take the callback passed to getJSON
, pass your own callback to jQuery.get
with 'text'
instead of 'json'
, parse the JSON using the custom reviver, and then call the original callback.
A complication is that the second parameter passed to getJSON
is optional (data to send with the request).
Assuming that you always use a success function (third and last argument), you can use rest parameters and pop()
to get the passed success function. Create a custom success function that takes the text response and uses the custom JSON.parse
, then calls the passed success function with the created object.
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>
The difference in the snippet output above vs the URL requested
https://jsonplaceholder.typicode.com/users
is that the latitude and longitude property values have been transformed into numbers, rather than remaining strings.
If you ever use await
as well without a success callback, then you'll need to overwrite the then
property of the returned Promise, though dealing with the optional success callback makes the code's logic a lot uglier:
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>