Skip to content

Commit

Permalink
[Console] Add support for JSON with long numerals
Browse files Browse the repository at this point in the history
Also:
* Add support for parsing and stringifying JSON with long numerals into `@osd/std`
* Upgrade `@opensearch/opensearch@2.3.0` which supports long numerals
* Add support for long numerals to `http/fetch`

Signed-off-by: Miki <miki@amazon.com>
  • Loading branch information
AMoo-Miki committed Jul 13, 2023
1 parent d746595 commit 0728d74
Show file tree
Hide file tree
Showing 15 changed files with 539 additions and 22 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- Enable plugins to augment visualizations with additional data and context ([#4361](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4361))
- Dashboard De-Angularization ([#4502](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4502))
- New management overview page and rename stack management to dashboard management ([#4287](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4287))
- [Console] Add support for JSON with long numerals ([#4562](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4562))
- [Vis Augmenter] Update base vis height in view events flyout ([#4535](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4535))

### 🐛 Bug Fixes
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@
"@hapi/podium": "^4.1.3",
"@hapi/vision": "^6.1.0",
"@hapi/wreck": "^17.1.0",
"@opensearch-project/opensearch": "^2.2.0",
"@opensearch-project/opensearch": "^2.3.0",
"@osd/ace": "1.0.0",
"@osd/analytics": "1.0.0",
"@osd/apm-config-loader": "1.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/osd-opensearch-archiver/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
},
"dependencies": {
"@osd/dev-utils": "1.0.0",
"@opensearch-project/opensearch": "^2.2.0"
"@opensearch-project/opensearch": "^2.3.0"
},
"devDependencies": {}
}
2 changes: 1 addition & 1 deletion packages/osd-opensearch/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"osd:watch": "../../scripts/use_node scripts/build --watch"
},
"dependencies": {
"@opensearch-project/opensearch": "^2.2.0",
"@opensearch-project/opensearch": "^2.3.0",
"@osd/dev-utils": "1.0.0",
"abort-controller": "^3.0.0",
"chalk": "^4.1.0",
Expand Down
19 changes: 19 additions & 0 deletions packages/osd-std/src/__snapshots__/json.test.ts.snap

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/osd-std/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@ export { unset } from './unset';
export { getFlattenedObject } from './get_flattened_object';
export { validateObject } from './validate_object';
export * from './rxjs_7';
export { parse, stringify } from './json';
176 changes: 176 additions & 0 deletions packages/osd-std/src/json.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { stringify, parse } from './json';

describe('json', () => {
it('can parse', () => {
const input = {
a: [
{ A: 1 },
{ B: '2' },
{ C: [1, 2, 3, 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'] },
],
b: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
c: {
i: {},
ii: [],
iii: '',
iv: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
},
};
const result = parse(JSON.stringify(input));
expect(result).toEqual(input);
});

it('can stringify', () => {
const input = {
a: [
{ A: 1 },
{ B: '2' },
{ C: [1, 2, 3, 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'] },
],
b: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
c: {
i: {},
ii: [],
iii: '',
iv: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
},
};
const result = stringify(input);
expect(result).toEqual(JSON.stringify(input));
});

it('can apply a reviver while parsing', () => {
const input = {
A: 255,
B: {
i: [[]],
ii: 'Lorem ipsum',
iii: {},
rand: Math.random(),
},
};
const text = JSON.stringify(input);
function reviver(this: any, key: string, val: any) {
if (Array.isArray(val) && toString.call(this) === '[object Object]') this._hasArrays = true;
else if (typeof val === 'string') val = `<![CDATA[${val}]]>`;
else if (typeof val === 'number') val = val.toString(16);
else if (toString.call(this) === '[object Object]' && key === 'rand' && val === input.B.rand)
this._found = true;
return val;
}

expect(parse(text, reviver)).toEqual(JSON.parse(text, reviver));
});

it('can apply a replacer and spaces while stringifying', () => {
const input = {
A: 255,
B: {
i: [[]],
ii: 'Lorem ipsum',
iii: {},
rand: Math.random(),
},
};

function replacer(this: any, key: string, val: any) {
if (Array.isArray(val) && val.length === 0) val.push('<empty>');
else if (typeof val === 'string') val = `<![CDATA[${val}]]>`;
else if (typeof val === 'number') val = val.toString(16);
else if (toString.call(this) === '[object Object]' && key === 'rand' && val === input.B.rand)
val = 1;
return val;
}

expect(stringify(input, replacer, 2)).toEqual(JSON.stringify(input, replacer, 2));
});

it('can handle long numerals while parsing', () => {
const longPositive = BigInt(Number.MAX_SAFE_INTEGER) * 2n;
const longNegative = BigInt(Number.MIN_SAFE_INTEGER) * 2n;
const text =
`{` +
// The space before and after the values, and the lack of spaces before comma are intentional
`"\\":${longPositive}": "[ ${longNegative.toString()}, ${longPositive.toString()} ]", ` +
`"positive": ${longPositive.toString()}, ` +
`"array": [ ${longNegative.toString()}, ${longPositive.toString()} ], ` +
`"negative": ${longNegative.toString()},` +
`"number": 102931203123987` +
`}`;

const result = parse(text);
expect(result.positive).toBe(longPositive);
expect(result.negative).toBe(longNegative);
expect(result.array).toEqual([longNegative, longPositive]);
expect(result['":' + longPositive]).toBe(
`[ ${longNegative.toString()}, ${longPositive.toString()} ]`
);
expect(result.number).toBe(102931203123987);
});

it('can handle BigInt values while stringifying', () => {
const longPositive = BigInt(Number.MAX_SAFE_INTEGER) * 2n;
const longNegative = BigInt(Number.MIN_SAFE_INTEGER) * 2n;
const input = {
[`": ${longPositive}`]: `[ ${longNegative.toString()}, ${longPositive.toString()} ]`,
positive: longPositive,
negative: longNegative,
array: [longNegative, longPositive],
number: 102931203123987,
};

expect(stringify(input)).toMatchSnapshot();
});

it('can apply a reviver on long numerals while parsing', () => {
const longPositive = BigInt(Number.MAX_SAFE_INTEGER) * 2n;
const longNegative = BigInt(Number.MIN_SAFE_INTEGER) * 2n;
const text =
`{` +
// The space before and after the values, and the lack of spaces before comma are intentional
`"\\":${longPositive}": "[ ${longNegative.toString()}, ${longPositive.toString()} ]", ` +
`"positive": ${longPositive.toString()}, ` +
`"array": [ ${longNegative.toString()}, ${longPositive.toString()} ], ` +
`"negative": ${longNegative.toString()},` +
`"number": 102931203123987` +
`}`;

const reviver = (key: string, val: any) => (typeof val === 'bigint' ? val * 3n : val);

const result = parse(text, reviver);
expect(result.positive).toBe(longPositive * 3n);
expect(result.negative).toBe(longNegative * 3n);
expect(result.array).toEqual([longNegative * 3n, longPositive * 3n]);
expect(result['":' + longPositive]).toBe(
`[ ${longNegative.toString()}, ${longPositive.toString()} ]`
);
expect(result.number).toBe(102931203123987);
});

it('can apply a replacer and spaces values while stringifying BigInts', () => {
const longPositive = BigInt(Number.MAX_SAFE_INTEGER) * 2n;
const longNegative = BigInt(Number.MIN_SAFE_INTEGER) * 2n;
const input = {
[`": ${longPositive}`]: `[ ${longNegative.toString()}, ${longPositive.toString()} ]`,
positive: longPositive,
negative: longNegative,
array: [longNegative, longPositive, []],
number: 102931203123987,
};

function replacer(this: any, key: string, val: any) {
if (typeof val === 'bigint') val = val * 3n;
else if (Array.isArray(val) && val.length === 0) val.push('<empty>');
else if (typeof val === 'string') val = `<![CDATA[${val}]]>`;
else if (typeof val === 'number') val = val.toString(16);
return val;
}

expect(stringify(input, replacer, 4)).toMatchSnapshot();
});
});
Loading

0 comments on commit 0728d74

Please sign in to comment.