I have an requirement to pass a some values from mobile to server in a web service call and so I am planning to pass all the values in JSON format like the below
<
I encountered the same need and make a universal solution (node+browser) that works with the Next.js framework, for instance.
It even works with circular dependencies (thanks to json-stringify-safe
).
Although, I also built a serializer on top of it to remove unnecessary data (because it's not recommended to use a url longer than 2k chars, see What is the maximum length of a URL in different browsers?)
import StringifySafe from 'json-stringify-safe';
export const encodeQueryParameter = (data: object): string => {
return encodeURIComponent(StringifySafe(data)); // Use StringifySafe to avoid crash on circular dependencies
};
export const decodeQueryParameter = (query: string): object => {
return JSON.parse(decodeURIComponent(query));
};
And the unit tests (jest):
import { decodeQueryParameter, encodeQueryParameter } from './url';
export const data = {
'organisation': {
'logo': {
'id': 'ck2xjm2oj9lr60b32c6l465vx',
'linkUrl': null,
'linkTarget': '_blank',
'classes': null,
'style': null,
'defaultTransformations': { 'width': 200, 'height': 200, '__typename': 'AssetTransformations' },
'mimeType': 'image/png',
'__typename': 'Asset',
},
'theme': {
'primaryColor': '#1134e6',
'primaryAltColor': '#203a51',
'secondaryColor': 'white',
'font': 'neuzeit-grotesk',
'__typename': 'Theme',
'primaryColorG1': '#ffffff',
},
},
};
export const encodedData = '%7B%22organisation%22%3A%7B%22logo%22%3A%7B%22id%22%3A%22ck2xjm2oj9lr60b32c6l465vx%22%2C%22linkUrl%22%3Anull%2C%22linkTarget%22%3A%22_blank%22%2C%22classes%22%3Anull%2C%22style%22%3Anull%2C%22defaultTransformations%22%3A%7B%22width%22%3A200%2C%22height%22%3A200%2C%22__typename%22%3A%22AssetTransformations%22%7D%2C%22mimeType%22%3A%22image%2Fpng%22%2C%22__typename%22%3A%22Asset%22%7D%2C%22theme%22%3A%7B%22primaryColor%22%3A%22%231134e6%22%2C%22primaryAltColor%22%3A%22%23203a51%22%2C%22secondaryColor%22%3A%22white%22%2C%22font%22%3A%22neuzeit-grotesk%22%2C%22__typename%22%3A%22Theme%22%2C%22primaryColorG1%22%3A%22%23ffffff%22%7D%7D%7D';
describe(`utils/url.ts`, () => {
describe(`encodeQueryParameter`, () => {
test(`should encode a JS object into a url-compatible string`, async () => {
expect(encodeQueryParameter(data)).toEqual(encodedData);
});
});
describe(`decodeQueryParameter`, () => {
test(`should decode a url-compatible string into a JS object`, async () => {
expect(decodeQueryParameter(encodedData)).toEqual(data);
});
});
describe(`encodeQueryParameter <> decodeQueryParameter <> encodeQueryParameter`, () => {
test(`should encode and decode multiple times without altering data`, async () => {
const _decodedData: object = decodeQueryParameter(encodedData);
expect(_decodedData).toEqual(data);
const _encodedData: string = encodeQueryParameter(_decodedData);
expect(_encodedData).toEqual(encodedData);
const _decodedDataAgain: object = decodeQueryParameter(_encodedData);
expect(_decodedDataAgain).toEqual(data);
});
});
});