Skip to content

Commit

Permalink
feat: add support for serializing complex objects
Browse files Browse the repository at this point in the history
Adds a `shouldSerializeValue` function which determines if a value
should be serialized or should attempt to be nested.

The default implementation checks if a value is a non-date object,
meaning all objects which are not dates will trigger nesting.
  • Loading branch information
43081j committed Jul 26, 2024
1 parent 5d0a39f commit 761f264
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 8 deletions.
5 changes: 3 additions & 2 deletions src/object-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ export function stringifyObject(
arrayRepeatSyntax = defaultOptions.arrayRepeatSyntax,
nesting = defaultOptions.nesting,
delimiter = defaultOptions.delimiter,
valueSerializer = defaultOptions.valueSerializer
valueSerializer = defaultOptions.valueSerializer,
shouldSerializeValue = defaultOptions.shouldSerializeValue
} = options;
const strDelimiter =
typeof delimiter === 'number' ? String.fromCharCode(delimiter) : delimiter;
Expand Down Expand Up @@ -96,7 +97,7 @@ export function stringifyObject(
result += strDelimiter;
}

if (typeof value === 'object' && value !== null) {
if (!shouldSerializeValue(value)) {
valueIsProbableArray = (value as unknown[]).pop !== undefined;

if (nesting || (arrayRepeat && valueIsProbableArray)) {
Expand Down
24 changes: 20 additions & 4 deletions src/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,13 @@ export type SerializeValueFunction = (
key: PropertyKey
) => string;

export type ShouldSerializeValueFunction = (value: unknown) => boolean;

export type DeserializeKeyFunction = (key: string) => PropertyKey;

export function defaultValueSerializer(value: unknown): string {
export const defaultValueSerializer: SerializeValueFunction = (
value: unknown
): string => {
switch (typeof value) {
case 'string':
// Length check is handled inside encodeString function
Expand All @@ -41,8 +45,18 @@ export function defaultValueSerializer(value: unknown): string {
break;
}

return '';
}
if (value === null || value === undefined) {
return '';
}

return encodeString(String(value));
};

export const defaultShouldSerializeValue: ShouldSerializeValueFunction = (
val
) => {
return typeof val !== 'object' || val === null || val instanceof Date;
};

export interface Options {
// Enable parsing nested objects and arrays
Expand Down Expand Up @@ -70,6 +84,7 @@ export interface Options {
valueDeserializer: DeserializeValueFunction;
keyDeserializer: DeserializeKeyFunction;
valueSerializer: SerializeValueFunction;
shouldSerializeValue: ShouldSerializeValueFunction;
}

const identityFunc = <T>(v: T): T => v;
Expand All @@ -82,5 +97,6 @@ export const defaultOptions: Options = {
delimiter: 38,
valueDeserializer: identityFunc,
valueSerializer: defaultValueSerializer,
keyDeserializer: identityFunc
keyDeserializer: identityFunc,
shouldSerializeValue: defaultShouldSerializeValue
};
11 changes: 9 additions & 2 deletions src/test/stringify_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as assert from 'node:assert/strict';
import {test} from 'node:test';
import {stringify} from '../main.js';
import {testCases} from './test-cases.js';
import {encodeString} from '../string-util.js';

test('stringify', async (t) => {
for (const testCase of testCases) {
Expand Down Expand Up @@ -40,9 +41,15 @@ test('stringify', async (t) => {
assert.equal(result, 'foo=400');
});

await t.test('skips infinite numbers', () => {
await t.test('date values', () => {
const date = new Date('2000-01-01');
const result = stringify({foo: date});
assert.equal(result, `foo=${encodeString(date.toString())}`);
});

await t.test('stringifies infinite numbers as Infinity', () => {
const result = stringify({foo: Infinity});
assert.equal(result, 'foo=');
assert.equal(result, 'foo=Infinity');
});

await t.test('non-objects result in empty string', () => {
Expand Down

0 comments on commit 761f264

Please sign in to comment.