Open joonseokhu opened 1 year ago
Yes, that's true - using the filter
option overrides the default filtering, which includes date serialization, as well as special handling for arrayFormat: 'comma'
.
One possibility would be to pass a third argument to filter
of defaultFilter
, so you could return defaultFilter(_, value);
and you'd get that default serialization - but we couldn't do that by default, or it'd be a breaking change.
Somewhat related to this.
Is there a way I can pass a custom prefix?
For example I have an object: { Age: [10,20] }
And want to serialize it so that it turns into: age[gte]=10&age[lte]=20
The current filter only lets me return the value but not a prefix. Am i missing something here?
@dbnar2 I think there's few options that you can choose.
The point is that you should translate the array into an object, and you can get the querystring with key inside of brakets
qs.stringify({ foo: [1, 2] }, { encodeValuesOnly: true });
// foo[0]=1&foo[1]=2
qs.stringify({ foo: { bar: 1, baz: 2 } }, { encodeValuesOnly: true });
// foo[bar]=1&foo[baz]=2
const data = {
myRange: [10, 20],
}
qs.stringify(data, {
encodeValuesOnly: true,
filter(key, value) {
if (key === 'myRange') {
const [gte, lte] = value
return { gte, lte }
}
// You have to serialize `Date` by yourself
if (value instanceof Date) {
return value.toISOString()
}
return value;
}
});
// myRange[gte]=10&myRange[lte]=20
/**
* returns true only if value is an array with 2 number elements.
*/
const isRange = (value: any): value is [number, number] => {
if (!Array.isArray(value)) return false;
if (value.length !== 2) return false;
if (value.some(el => typeof el !== 'number')) return false;
return true;
}
const data = {
myRange: [10, 20],
}
qs.stringify(data, {
encodeValuesOnly: true,
filter(key, value) {
if (isRange(value)) {
const [gte, lte] = value
return { gte, lte }
}
// You have to serialize `Date` by yourself
if (value instanceof Date) {
return value.toISOString()
}
return value;
}
});
// myRange[gte]=10&myRange[lte]=20
qs
const toNumberRange = ([gte, lte]: [number, number]) => {
return { gte, lte }
}
const data = {
myRange: toNumberRange([10, 20]),
}
qs.stringify(data, {
encodeValuesOnly: true,
});
// myRange[gte]=10&myRange[lte]=20
Yes, that's true - using the
filter
option overrides the default filtering, which includes date serialization, as well as special handling forarrayFormat: 'comma'
.One possibility would be to pass a third argument to
filter
ofdefaultFilter
, so you couldreturn defaultFilter(_, value);
and you'd get that default serialization - but we couldn't do that by default, or it'd be a breaking change.
Are there any plans for this to be fixed soon? I am willing to contribute.
@carpics if there's a way to provide this capability without a breaking change, i'd love to hear about it.
serialization for
Date
type values are skipped when I'm usinngfilter
option for custom serialization.code to reproduce
what I expected
what actually worked
so I have to call
qs.stringify
like this: