Skip to content

Allow numeric steps when retrieving array elemetn #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions src/__tests__/get.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import {get} from '../get';
import {test, expect} from 'vitest';
import {parseJsonPointer} from '../util';

test('can find number root', () => {
const res = get(123, []);
expect(res).toBe(123);
});

test('can find string root', () => {
const res = get('foo', []);
expect(res).toBe('foo');
});

test('can find key in object', () => {
const res = get({foo: 'bar'}, ['foo']);
expect(res).toBe('bar');
});

test('can retrieve withing deep object', () => {
const res = get({foo: {bar: {baz: 'qux', a: 1}}}, ['foo', 'bar', 'baz']);
expect(res).toEqual('qux');
});

test('simple key in simple object', () => {
const doc = {a: 123};
const path = parseJsonPointer('/a');
const res = get(doc, path);
expect(res).toEqual(123);
});

test('returns "undefined" when referencing missing key with multiple steps', () => {
const doc = {a: 123};
const path = parseJsonPointer('/b/c');
expect(get(doc, path)).toBe(undefined);
});

test('can reference array element', () => {
const doc = {a: {b: [1, 2, 3]}};
const path = parseJsonPointer('/a/b/1');
const res = get(doc, path);
expect(res).toEqual(2);
});

test('returns "undefined" when referencing end of array', () => {
const doc = {a: {b: [1, 2, 3]}};
const path = parseJsonPointer('/a/b/-');
const res = get(doc, path);
expect(res).toBe(undefined);
});

test('returns undefined when pointing past array boundary', () => {
const doc = {a: {b: [1, 2, 3]}};
const path = parseJsonPointer('/a/b/-1');
expect(get(doc, path)).toBe(undefined);
});

test('missing object key returns undefined', () => {
const doc = {foo: 123};
const path = parseJsonPointer('/bar');
const res = get(doc, path);
expect(res).toBe(undefined);
});

test('can reference array element by number step', () => {
const doc = [1, 2, 3];
expect(get(doc, [0])).toBe(1);
expect(get(doc, [1])).toBe(2);
expect(get(doc, [2])).toBe(3);
expect(get(doc, [3])).toBe(undefined);
});

test('can reference array element by number step', () => {
const doc = {foo: {bar: [1, 2, 3]}};
expect(get(doc, ['foo', 'bar', 0])).toBe(1);
expect(get(doc, ['foo', 'bar', 1])).toBe(2);
expect(get(doc, ['foo', 'bar', 2])).toBe(3);
expect(get(doc, ['foo', 'bar', 3])).toBe(undefined);
});
11 changes: 6 additions & 5 deletions src/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ export const get = (val: unknown, path: Path): unknown | undefined => {
for (let i = 0; i < pathLength; i++) {
key = path[i];
if (val instanceof Array) {
if (key === '-') return undefined;
const key2 = ~~key;
if ('' + key2 !== key) return undefined;
key = key2;
if (key < 0) return undefined;
if (typeof key !== 'number') {
if (key === '-') return undefined;
const key2 = ~~key;
if ('' + key2 !== key) return undefined;
key = key2;
}
val = val[key];
} else if (typeof val === 'object') {
if (!val || !has(val as object, key as string)) return undefined;
Expand Down