Skip to content

Commit

Permalink
fix(sdk)!: change Json.get() and Json.getAt() to throw (#4034)
Browse files Browse the repository at this point in the history
Currently `Json.get()` and `Json.getAt()` don't throw any error if the JSON property you are accessing doesn't exist.

Besides, the descriptions of the methods say that they can return `undefined`, which is not true: it's not specified in the return values and that's actually the scope of `Json.tryGet()` and `Json.tryGetAt()`.

- [x] Fix `Json.get()`
- [x] Fix `Json.getAt()`

*By submitting this pull request, I confirm that my contribution is made under the terms of the [Wing Cloud Contribution License](https://github.com/winglang/wing/blob/main/CONTRIBUTION_LICENSE.md)*.
  • Loading branch information
garysassano authored Sep 3, 2023
1 parent 8efa0bb commit cd3651f
Show file tree
Hide file tree
Showing 26 changed files with 476 additions and 164 deletions.
12 changes: 6 additions & 6 deletions docs/docs/04-standard-library/02-std/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -687,7 +687,7 @@ Immutable Json.
| <code><a href="#@winglang/sdk.std.Json.asBool">asBool</a></code> | Convert Json element to boolean if possible. |
| <code><a href="#@winglang/sdk.std.Json.asNum">asNum</a></code> | Convert Json element to number if possible. |
| <code><a href="#@winglang/sdk.std.Json.asStr">asStr</a></code> | Convert Json element to string if possible. |
| <code><a href="#@winglang/sdk.std.Json.get">get</a></code> | Returns a specified element from the Json. |
| <code><a href="#@winglang/sdk.std.Json.get">get</a></code> | Returns the value associated with the specified Json key. |
| <code><a href="#@winglang/sdk.std.Json.getAt">getAt</a></code> | Returns a specified element at a given index from Json Array. |
| <code><a href="#@winglang/sdk.std.Json.tryAsBool">tryAsBool</a></code> | Convert Json element to boolean if possible. |
| <code><a href="#@winglang/sdk.std.Json.tryAsNum">tryAsNum</a></code> | Convert Json element to number if possible. |
Expand Down Expand Up @@ -727,13 +727,13 @@ Convert Json element to string if possible.
get(key: str): Json
```

Returns a specified element from the Json.
Returns the value associated with the specified Json key.

###### `key`<sup>Required</sup> <a name="key" id="@winglang/sdk.std.Json.get.parameter.key"></a>

- *Type:* str

The key of the element to return.
The key of the Json property.

---

Expand Down Expand Up @@ -1348,7 +1348,7 @@ Mutable Json.
| <code><a href="#@winglang/sdk.std.MutJson.asBool">asBool</a></code> | Convert Json element to boolean if possible. |
| <code><a href="#@winglang/sdk.std.MutJson.asNum">asNum</a></code> | Convert Json element to number if possible. |
| <code><a href="#@winglang/sdk.std.MutJson.asStr">asStr</a></code> | Convert Json element to string if possible. |
| <code><a href="#@winglang/sdk.std.MutJson.get">get</a></code> | Returns a specified element from the Json. |
| <code><a href="#@winglang/sdk.std.MutJson.get">get</a></code> | Returns the value associated with the specified Json key. |
| <code><a href="#@winglang/sdk.std.MutJson.getAt">getAt</a></code> | Returns a specified element at a given index from MutJson Array. |
| <code><a href="#@winglang/sdk.std.MutJson.set">set</a></code> | Adds or updates an element in MutJson with a specific key and value. |
| <code><a href="#@winglang/sdk.std.MutJson.setAt">setAt</a></code> | Set element in MutJson Array with a specific key and value. |
Expand Down Expand Up @@ -1390,13 +1390,13 @@ Convert Json element to string if possible.
get(key: str): MutJson
```

Returns a specified element from the Json.
Returns the value associated with the specified Json key.

###### `key`<sup>Required</sup> <a name="key" id="@winglang/sdk.std.MutJson.get.parameter.key"></a>

- *Type:* str

The key of the element to return.
The key of the Json property.

---

Expand Down
111 changes: 75 additions & 36 deletions examples/tests/sdk_tests/std/json.w
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,86 @@
//-----------------------------------------------------------------------------
bring cloud;

// set() & get()
let a = MutJson { a: 1 };
let b = MutJson { b: 2 };
a.set("c", b);
test "get()" {
let assertThrows = (expected: str, block: (): void) => {
let var error = false;
try {
block();
} catch actual {
assert(actual == expected);
error = true;
}
assert(error);
};

let c = a.get("c");
assert(c.get("b") == 2);
let JSON_PROPERTY_DOES_NOT_EXIST_ERROR = "Json property \"c\" does not exist";
let obj = Json { a: 1, b: 2 };
let mutObj = MutJson { a: 1, b: 2 };

test "set()" {
let x = MutJson { a: 1 };
x.set("b", 2);
let y = x.get("b");
assert(y == 2);
assert(obj.get("b") == 2);
assert(mutObj.get("b") == 2);

assertThrows(JSON_PROPERTY_DOES_NOT_EXIST_ERROR, () => {
obj.get("c");
});
assertThrows(JSON_PROPERTY_DOES_NOT_EXIST_ERROR, () => {
mutObj.get("c");
});
}

//-----------------------------------------------------------------------------
// setAt() & getAt()
let d = MutJson { d: 3 };
a.setAt(2, d);
let e = a.getAt(2);
assert(e.get("d") == 3);
test "getAt()" {
let assertThrows = (expected: str, block: (): void) => {
let var error = false;
try {
block();
} catch actual {
assert(actual == expected);
error = true;
}
assert(error);
};

let INDEX_OUT_OF_BOUNDS_ERROR = "Index out of bounds";
let jsonArray = Json ["foo", "bar", "baz"];
let mutJsonArray = MutJson [1, 2, 3];

assert(jsonArray.getAt(2) == "baz");
assert(mutJsonArray.getAt(2) == 3);

assertThrows(INDEX_OUT_OF_BOUNDS_ERROR, () => {
jsonArray.getAt(3);
mutJsonArray.getAt(3);
});
}

test "set()" {
let mutObj = MutJson { x: 1, y: 2 };

mutObj.set("x", -1);
mutObj.set("z", 3);

assert(mutObj.get("x") == -1);
assert(mutObj.get("z") == 3);
}

test "setAt()" {
let x = MutJson { a: 1 };
let a = MutJson { c: 3 };
x.setAt(2, a);
let d = x.getAt(2);
assert(d.get("c") == 3);
let mutJsonArray = MutJson [1, 2, 3];

mutJsonArray.setAt(0, -1);
mutJsonArray.setAt(3, 3);

assert(mutJsonArray.getAt(0) == -1);
assert(mutJsonArray.getAt(3) == 3);
}

test "stringify()" {
let obj = Json { a: 1, b: 2 };

let stringified = Json.stringify(obj);
let stringifiedIndent = Json.stringify(obj, indent: 2);

assert(stringified == "{\"a\":1,\"b\":2}");
assert(stringifiedIndent == "{\n \"a\": 1,\n \"b\": 2\n}");
}

//-----------------------------------------------------------------------------
Expand All @@ -53,17 +105,4 @@ try {
log(error);
assert(error == "");
}
*/

//-----------------------------------------------------------------------------
// stringify()

test "stringify()" {
let obj = Json { a: 1, b: 2 };

let stringified = Json.stringify(obj);
let stringifiedIndent = Json.stringify(obj, indent: 2);

assert(stringified == "{\"a\":1,\"b\":2}");
assert(stringifiedIndent == "{\n \"a\": 1,\n \"b\": 2\n}");
}
*/
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ source: libs/wingc/src/lsp/completions.rs
detail: "(key: str): MutJson"
documentation:
kind: markdown
value: "```wing\nget: (key: str): MutJson\n```\n---\nReturns a specified element from the Json.\n\n\n### Returns\nThe element associated with the specified key, or undefined if the key can't be found"
value: "```wing\nget: (key: str): MutJson\n```\n---\nReturns the value associated with the specified Json key.\n\n\n### Returns\nThe value associated with the specified Json key\n\n*@throws* *Json property does not exist if the given key is not part of an existing property*"
sortText: ff|get
insertText: get($0)
insertTextFormat: 2
Expand All @@ -42,7 +42,7 @@ source: libs/wingc/src/lsp/completions.rs
detail: "(index: num): MutJson"
documentation:
kind: markdown
value: "```wing\ngetAt: (index: num): MutJson\n```\n---\nReturns a specified element at a given index from MutJson Array.\n\n\n### Returns\nThe element at given index in MutJson Array, or undefined if index is not valid"
value: "```wing\ngetAt: (index: num): MutJson\n```\n---\nReturns a specified element at a given index from MutJson Array.\n\n\n### Returns\nThe element at given index in MutJson Array\n\n*@throws* *index out of bounds error if the given index does not exist for the MutJson Array*"
sortText: ff|getAt
insertText: getAt($0)
insertTextFormat: 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ source: libs/wingc/src/lsp/completions.rs
detail: "(key: str): Json"
documentation:
kind: markdown
value: "```wing\nget: (key: str): Json\n```\n---\nReturns a specified element from the Json.\n\n\n### Returns\nThe element associated with the specified key, or undefined if the key can't be found"
value: "```wing\nget: (key: str): Json\n```\n---\nReturns the value associated with the specified Json key.\n\n\n### Returns\nThe value associated with the specified Json key\n\n*@throws* *Json property does not exist if the given key is not part of an existing property*"
sortText: ff|get
insertText: get($0)
insertTextFormat: 2
Expand All @@ -42,7 +42,7 @@ source: libs/wingc/src/lsp/completions.rs
detail: "(index: num): Json"
documentation:
kind: markdown
value: "```wing\ngetAt: (index: num): Json\n```\n---\nReturns a specified element at a given index from Json Array.\n\n\n### Returns\nThe element at given index in Json Array, or undefined if index is not valid"
value: "```wing\ngetAt: (index: num): Json\n```\n---\nReturns a specified element at a given index from Json Array.\n\n\n### Returns\nThe element at given index in Json Array\n\n*@throws* *index out of bounds error if the given index does not exist for the Json Array*"
sortText: ff|getAt
insertText: getAt($0)
insertTextFormat: 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ source: libs/wingc/src/lsp/completions.rs
detail: "(key: str): Json"
documentation:
kind: markdown
value: "```wing\nget: (key: str): Json\n```\n---\nReturns a specified element from the Json.\n\n\n### Returns\nThe element associated with the specified key, or undefined if the key can't be found"
value: "```wing\nget: (key: str): Json\n```\n---\nReturns the value associated with the specified Json key.\n\n\n### Returns\nThe value associated with the specified Json key\n\n*@throws* *Json property does not exist if the given key is not part of an existing property*"
sortText: ff|get
insertText: get($0)
insertTextFormat: 2
Expand All @@ -78,7 +78,7 @@ source: libs/wingc/src/lsp/completions.rs
detail: "(index: num): Json"
documentation:
kind: markdown
value: "```wing\ngetAt: (index: num): Json\n```\n---\nReturns a specified element at a given index from Json Array.\n\n\n### Returns\nThe element at given index in Json Array, or undefined if index is not valid"
value: "```wing\ngetAt: (index: num): Json\n```\n---\nReturns a specified element at a given index from Json Array.\n\n\n### Returns\nThe element at given index in Json Array\n\n*@throws* *index out of bounds error if the given index does not exist for the Json Array*"
sortText: ff|getAt
insertText: getAt($0)
insertTextFormat: 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ source: libs/wingc/src/lsp/completions.rs
detail: "(key: str): Json"
documentation:
kind: markdown
value: "```wing\nget: (key: str): Json\n```\n---\nReturns a specified element from the Json.\n\n\n### Returns\nThe element associated with the specified key, or undefined if the key can't be found"
value: "```wing\nget: (key: str): Json\n```\n---\nReturns the value associated with the specified Json key.\n\n\n### Returns\nThe value associated with the specified Json key\n\n*@throws* *Json property does not exist if the given key is not part of an existing property*"
sortText: ff|get
insertText: get($0)
insertTextFormat: 2
Expand All @@ -42,7 +42,7 @@ source: libs/wingc/src/lsp/completions.rs
detail: "(index: num): Json"
documentation:
kind: markdown
value: "```wing\ngetAt: (index: num): Json\n```\n---\nReturns a specified element at a given index from Json Array.\n\n\n### Returns\nThe element at given index in Json Array, or undefined if index is not valid"
value: "```wing\ngetAt: (index: num): Json\n```\n---\nReturns a specified element at a given index from Json Array.\n\n\n### Returns\nThe element at given index in Json Array\n\n*@throws* *index out of bounds error if the given index does not exist for the Json Array*"
sortText: ff|getAt
insertText: getAt($0)
insertTextFormat: 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ source: libs/wingc/src/lsp/hover.rs
---
contents:
kind: markdown
value: "```wing\nget: (key: str): Json\n```\n---\nReturns a specified element from the Json.\n\n\n### Returns\nThe element associated with the specified key, or undefined if the key can't be found"
value: "```wing\nget: (key: str): Json\n```\n---\nReturns the value associated with the specified Json key.\n\n\n### Returns\nThe value associated with the specified Json key\n\n*@throws* *Json property does not exist if the given key is not part of an existing property*"
range:
start:
line: 2
Expand Down
28 changes: 16 additions & 12 deletions libs/wingsdk/src/std/json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,13 @@ export class Json {
private constructor() {}

/**
* Returns a specified element from the Json.
* Returns the value associated with the specified Json key
*
* @macro ($self$)[$args$]
* @macro ((obj, args) => { if (obj[args] === undefined) throw new Error(`Json property "${args}" does not exist`); return obj[args] })($self$, $args$)
*
* @param key The key of the element to return
* @returns The element associated with the specified key, or undefined if the key can't be found
* @param key The key of the Json property
* @returns The value associated with the specified Json key
* @throws Json property does not exist if the given key is not part of an existing property
*/
public get(key: string): Json {
key;
Expand All @@ -161,10 +162,11 @@ export class Json {
/**
* Returns a specified element at a given index from Json Array
*
* @macro ($self$)[$args$]
* @macro ((obj, args) => { if (obj[args] === undefined) throw new Error("Index out of bounds"); return obj[args] })($self$, $args$)
*
* @param index The index of the element in the Json Array to return
* @returns The element at given index in Json Array, or undefined if index is not valid
* @returns The element at given index in Json Array
* @throws index out of bounds error if the given index does not exist for the Json Array
*/
public getAt(index: number): Json {
index;
Expand Down Expand Up @@ -278,12 +280,13 @@ export class MutJson {
private constructor() {}

/**
* Returns a specified element from the Json.
* Returns the value associated with the specified Json key
*
* @macro ($self$)[$args$]
* @macro ((obj, args) => { if (obj[args] === undefined) throw new Error(`Json property "${args}" does not exist`); return obj[args] })($self$, $args$)
*
* @param key The key of the element to return
* @returns The element associated with the specified key, or undefined if the key can't be found
* @param key The key of the Json property
* @returns The value associated with the specified Json key
* @throws Json property does not exist if the given key is not part of an existing property
*/
public get(key: string): MutJson {
key;
Expand All @@ -293,10 +296,11 @@ export class MutJson {
/**
* Returns a specified element at a given index from MutJson Array
*
* @macro ($self$)[$args$]
* @macro ((obj, args) => { if (obj[args] === undefined) throw new Error("Index out of bounds"); return obj[args] })($self$, $args$)
*
* @param index The index of the element in the MutJson Array to return
* @returns The element at given index in MutJson Array, or undefined if index is not valid
* @returns The element at given index in MutJson Array
* @throws index out of bounds error if the given index does not exist for the MutJson Array
*/
public getAt(index: number): MutJson {
index;
Expand Down
6 changes: 3 additions & 3 deletions tools/hangar/__snapshots__/error.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ exports[`bool_from_json.w 1`] = `
../../../examples/tests/error/target/test/bool_from_json.wsim.[REDACTED].tmp/.wing/preflight.js:9
super(scope, id);
const j = ({\\"a\\": 123});
>> const a = (std.Boolean.fromJson((j)[\\"a\\"]));
>> const a = (std.Boolean.fromJson(((obj, args) => { if (obj[args] === undefined) throw new Error(\`Json property \\"\${args}\\" does not exist\`); return obj[args] })(j, \\"a\\")));
}
}
Expand Down Expand Up @@ -40,7 +40,7 @@ exports[`number_from_json.w 1`] = `
../../../examples/tests/error/target/test/number_from_json.wsim.[REDACTED].tmp/.wing/preflight.js:9
super(scope, id);
const j = ({\\"a\\": \\"apples\\"});
>> const a = ((args) => { if (typeof args !== \\"number\\") {throw new Error(\\"unable to parse \\" + typeof args + \\" \\" + args + \\" as a number\\")}; return JSON.parse(JSON.stringify(args)) })((j)[\\"a\\"]);
>> const a = ((args) => { if (typeof args !== \\"number\\") {throw new Error(\\"unable to parse \\" + typeof args + \\" \\" + args + \\" as a number\\")}; return JSON.parse(JSON.stringify(args)) })(((obj, args) => { if (obj[args] === undefined) throw new Error(\`Json property \\"\${args}\\" does not exist\`); return obj[args] })(j, \\"a\\"));
}
}
Expand Down Expand Up @@ -103,7 +103,7 @@ exports[`string_from_json.w 1`] = `
../../../examples/tests/error/target/test/string_from_json.wsim.[REDACTED].tmp/.wing/preflight.js:9
super(scope, id);
const j = ({\\"a\\": 123});
>> const a = ((args) => { if (typeof args !== \\"string\\") {throw new Error(\\"unable to parse \\" + typeof args + \\" \\" + args + \\" as a string\\")}; return JSON.parse(JSON.stringify(args)) })((j)[\\"a\\"]);
>> const a = ((args) => { if (typeof args !== \\"string\\") {throw new Error(\\"unable to parse \\" + typeof args + \\" \\" + args + \\" as a string\\")}; return JSON.parse(JSON.stringify(args)) })(((obj, args) => { if (obj[args] === undefined) throw new Error(\`Json property \\"\${args}\\" does not exist\`); return obj[args] })(j, \\"a\\"));
}
}
Expand Down
Loading

0 comments on commit cd3651f

Please sign in to comment.