feat(json-prettify): sort keys

This commit is contained in:
Corentin Thomasset 2023-03-29 23:25:39 +02:00 committed by Corentin THOMASSET
parent 863c8d0f6a
commit 3b625fd473
3 changed files with 69 additions and 3 deletions

View file

@ -1,4 +1,15 @@
<template>
<div style="flex: 0 0 100%">
<n-space style="margin: 0 auto; max-width: 600px" justify="center">
<n-form-item label="Sort keys :" label-placement="left" label-width="100">
<n-switch v-model:value="sortKeys" />
</n-form-item>
<n-form-item label="Indent size :" label-placement="left" label-width="100" :show-feedback="false">
<n-input-number v-model:value="indentSize" min="0" max="10" style="width: 100px" />
</n-form-item>
</n-space>
</div>
<n-form-item
label="Your raw json"
:feedback="rawJsonValidation.message"
@ -25,13 +36,17 @@
import TextareaCopyable from '@/components/TextareaCopyable.vue';
import { useValidation } from '@/composable/validation';
import { withDefaultOnError } from '@/utils/defaults';
import JSON5 from 'json5';
import { computed, ref } from 'vue';
import JSON5 from 'json5';
import { useStorage } from '@vueuse/core';
import { formatJson } from './json.models';
const inputElement = ref<HTMLElement>();
const rawJson = ref('{"hello": "world"}');
const cleanJson = computed(() => withDefaultOnError(() => JSON.stringify(JSON5.parse(rawJson.value), null, 3), ''));
const rawJson = useStorage('json-prettify:raw-json', '{"hello": "world", "foo": "bar"}');
const indentSize = useStorage('json-prettify:indent-size', 3);
const sortKeys = useStorage('json-prettify:sort-keys', true);
const cleanJson = computed(() => withDefaultOnError(() => formatJson({ rawJson, indentSize, sortKeys }), ''));
const rawJsonValidation = useValidation({
source: rawJson,

View file

@ -0,0 +1,16 @@
import { describe, expect, it } from 'vitest';
import { sortObjectKeys } from './json.models';
describe('json models', () => {
describe('sortObjectKeys', () => {
it('the object keys are recursively sorted alphabetically', () => {
expect(JSON.stringify(sortObjectKeys({ b: 2, a: 1 }))).to.deep.equal(JSON.stringify({ a: 1, b: 2 }));
// To unsure that this way of testing is working
expect(JSON.stringify(sortObjectKeys({ b: 2, a: 1 }))).to.not.deep.equal(JSON.stringify({ b: 2, a: 1 }));
expect(JSON.stringify(sortObjectKeys({ b: 2, a: 1, d: { j: 7, a: [{ z: 9, y: 8 }] }, c: 3 }))).to.deep.equal(
JSON.stringify({ a: 1, b: 2, c: 3, d: { a: [{ y: 8, z: 9 }], j: 7 } }),
);
});
});
});

View file

@ -0,0 +1,35 @@
import { get, type MaybeRef } from '@vueuse/core';
import JSON5 from 'json5';
export { sortObjectKeys, formatJson };
function sortObjectKeys<T>(obj: T): T {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
if (Array.isArray(obj)) {
return obj.map(sortObjectKeys) as T;
}
return Object.keys(obj)
.sort()
.reduce((sortedObj, key) => {
sortedObj[key] = sortObjectKeys((obj as Record<string, unknown>)[key]);
return sortedObj;
}, {} as Record<string, unknown>) as T;
}
function formatJson({
rawJson,
sortKeys = true,
indentSize = 3,
}: {
rawJson: MaybeRef<string>;
sortKeys?: MaybeRef<boolean>;
indentSize?: MaybeRef<number>;
}) {
const parsedObject = JSON5.parse(get(rawJson));
return JSON.stringify(get(sortKeys) ? sortObjectKeys(parsedObject) : parsedObject, null, get(indentSize));
}