Skip to content

Commit 16815cd

Browse files
authored
Merge pull request #1 from jsonjoy-com/fix-get
Allow numeric steps when retrieving array elemetn
2 parents 8a77a90 + 20d2f7e commit 16815cd

File tree

2 files changed

+85
-5
lines changed

2 files changed

+85
-5
lines changed

src/__tests__/get.spec.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import {get} from '../get';
2+
import {test, expect} from 'vitest';
3+
import {parseJsonPointer} from '../util';
4+
5+
test('can find number root', () => {
6+
const res = get(123, []);
7+
expect(res).toBe(123);
8+
});
9+
10+
test('can find string root', () => {
11+
const res = get('foo', []);
12+
expect(res).toBe('foo');
13+
});
14+
15+
test('can find key in object', () => {
16+
const res = get({foo: 'bar'}, ['foo']);
17+
expect(res).toBe('bar');
18+
});
19+
20+
test('can retrieve withing deep object', () => {
21+
const res = get({foo: {bar: {baz: 'qux', a: 1}}}, ['foo', 'bar', 'baz']);
22+
expect(res).toEqual('qux');
23+
});
24+
25+
test('simple key in simple object', () => {
26+
const doc = {a: 123};
27+
const path = parseJsonPointer('/a');
28+
const res = get(doc, path);
29+
expect(res).toEqual(123);
30+
});
31+
32+
test('returns "undefined" when referencing missing key with multiple steps', () => {
33+
const doc = {a: 123};
34+
const path = parseJsonPointer('/b/c');
35+
expect(get(doc, path)).toBe(undefined);
36+
});
37+
38+
test('can reference array element', () => {
39+
const doc = {a: {b: [1, 2, 3]}};
40+
const path = parseJsonPointer('/a/b/1');
41+
const res = get(doc, path);
42+
expect(res).toEqual(2);
43+
});
44+
45+
test('returns "undefined" when referencing end of array', () => {
46+
const doc = {a: {b: [1, 2, 3]}};
47+
const path = parseJsonPointer('/a/b/-');
48+
const res = get(doc, path);
49+
expect(res).toBe(undefined);
50+
});
51+
52+
test('returns undefined when pointing past array boundary', () => {
53+
const doc = {a: {b: [1, 2, 3]}};
54+
const path = parseJsonPointer('/a/b/-1');
55+
expect(get(doc, path)).toBe(undefined);
56+
});
57+
58+
test('missing object key returns undefined', () => {
59+
const doc = {foo: 123};
60+
const path = parseJsonPointer('/bar');
61+
const res = get(doc, path);
62+
expect(res).toBe(undefined);
63+
});
64+
65+
test('can reference array element by number step', () => {
66+
const doc = [1, 2, 3];
67+
expect(get(doc, [0])).toBe(1);
68+
expect(get(doc, [1])).toBe(2);
69+
expect(get(doc, [2])).toBe(3);
70+
expect(get(doc, [3])).toBe(undefined);
71+
});
72+
73+
test('can reference array element by number step', () => {
74+
const doc = {foo: {bar: [1, 2, 3]}};
75+
expect(get(doc, ['foo', 'bar', 0])).toBe(1);
76+
expect(get(doc, ['foo', 'bar', 1])).toBe(2);
77+
expect(get(doc, ['foo', 'bar', 2])).toBe(3);
78+
expect(get(doc, ['foo', 'bar', 3])).toBe(undefined);
79+
});

src/get.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ export const get = (val: unknown, path: Path): unknown | undefined => {
88
for (let i = 0; i < pathLength; i++) {
99
key = path[i];
1010
if (val instanceof Array) {
11-
if (key === '-') return undefined;
12-
const key2 = ~~key;
13-
if ('' + key2 !== key) return undefined;
14-
key = key2;
15-
if (key < 0) return undefined;
11+
if (typeof key !== 'number') {
12+
if (key === '-') return undefined;
13+
const key2 = ~~key;
14+
if ('' + key2 !== key) return undefined;
15+
key = key2;
16+
}
1617
val = val[key];
1718
} else if (typeof val === 'object') {
1819
if (!val || !has(val as object, key as string)) return undefined;

0 commit comments

Comments
 (0)