dirac-json 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/TODO.md CHANGED
@@ -7,15 +7,15 @@
7
7
  ## 🔴 High Priority
8
8
 
9
9
  ### Pending
10
- - [ ] **Path query syntax**: Implement dot notation access
11
- - Target syntax: `<json path="a.b.c">{"a":{"b":{"c":"value"}}}</json>` → "value"
12
- - Should work with nested objects and arrays
13
- - Handle edge cases: missing keys, null values, array indices
10
+ - [ ] **npm publishing**: Publish as standalone package
11
+ - Currently local project
12
+ - Version 0.1.0 target
13
+ - All tests passing (17/17)
14
14
 
15
15
  ## 🟡 Medium Priority
16
16
 
17
17
  ### Pending
18
- - [ ] **Array operations**: Support array indexing and iteration
18
+ - [ ] **Array operations enhancement**: Support more array methods within JSON objects
19
19
  - Syntax: `path="items[0].name"` for array access
20
20
  - Consider: array length, map, filter operations
21
21
 
@@ -45,6 +45,29 @@
45
45
 
46
46
  ## ✅ Completed
47
47
 
48
+ - [x] **Testing suite** (v0.1.0)
49
+ - Created 17 comprehensive unit tests
50
+ - Coverage: All array operations (get, push, pop, shift, unshift, length)
51
+ - Coverage: All JSON object operations (getKeys, get key/path, has, set, stringify)
52
+ - Test patterns: Simple operations, path traversal, iteration, edge cases
53
+ - Test framework: Using dirac test-runner with TEST/EXPECT comments
54
+ - All 17 tests passing ✓
55
+ - Test command: `npm test`
56
+
57
+ - [x] **Object operations with path syntax** (v0.1.0)
58
+ - Implemented `<json name="var">` pattern matching `<array>` syntax
59
+ - Operations: `<getKeys />`, `<get key="" jsonPath="" />`, `<set key="">`, `<has key="" />`, `<stringify indent="" />`
60
+ - Path parser supports dot notation (`a.b.c`) and array indices (`items[0].name`)
61
+ - Fixed namespace conflict: renamed `param-path` to `param-jsonPath` to avoid Node.js `path` module collision
62
+ - Tests: All 8 test cases passing in `tests/json-object.test.di`
63
+ - Key features:
64
+ - Simple key access: `<get key="field" />`
65
+ - Path access: `<get jsonPath="a.b.c" />` or `<get jsonPath="items[0].name" />`
66
+ - Variable substitution: `<get key="${varKey}" />`
67
+ - Object iteration: `<getKeys />` returns array, iterate with `<loop>`
68
+ - Existence check: `<has key="field" />` returns boolean
69
+ - Pretty printing: `<stringify indent="2" />`
70
+
48
71
  - [x] **Basic library structure**
49
72
  - Created lib/index.di
50
73
  - Basic README with examples
@@ -0,0 +1,18 @@
1
+ <!-- Test array iteration without destruction -->
2
+ <import src="../lib/index.di" />
3
+
4
+ <defvar name="packages">["pkg1", "pkg2", "pkg3"]</defvar>
5
+
6
+ <output>Array length: <array name="packages"><length /></array></output>
7
+
8
+ <output>First pass - getting by index:</output>
9
+ <output> Item 0: <array name="packages"><get index="0" /></array></output>
10
+ <output> Item 1: <array name="packages"><get index="1" /></array></output>
11
+ <output> Item 2: <array name="packages"><get index="2" /></array></output>
12
+
13
+ <output>Second pass - array still has all items:</output>
14
+ <output> Item 0: <array name="packages"><get index="0" /></array></output>
15
+ <output> Item 1: <array name="packages"><get index="1" /></array></output>
16
+ <output> Item 2: <array name="packages"><get index="2" /></array></output>
17
+
18
+ <output>Done - array is unchanged</output>
package/lib/index.di CHANGED
@@ -44,6 +44,152 @@
44
44
  </eval>
45
45
  </subroutine>
46
46
 
47
+ <!-- json: JSON object operations with nested operation tags -->
48
+ <subroutine name="json" param-name="string:required:JSON object variable name">
49
+
50
+ <!-- getKeys: Get array of object keys -->
51
+ <subroutine name="getKeys">
52
+ <eval name="result">
53
+ let objValue;
54
+ for (let i = session.variables.length - 1; i >= 0; i--) {
55
+ if (session.variables[i].name === name) {
56
+ objValue = session.variables[i].value;
57
+ break;
58
+ }
59
+ }
60
+ let obj = typeof objValue === 'string' ? JSON.parse(objValue) : objValue;
61
+ if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
62
+ throw new Error(`Variable ${name} is not a JSON object`);
63
+ }
64
+ return JSON.stringify(Object.keys(obj));
65
+ </eval>
66
+ <output><variable name="result" /></output>
67
+ </subroutine>
68
+
69
+ <!--get: Get value by key or jsonPath -->
70
+ <subroutine name="get" param-key="string:optional:object key" param-jsonPath="string:optional:path with dot notation or array indices">
71
+ <eval name="result">
72
+ let objValue;
73
+ for (let i = session.variables.length - 1; i >= 0; i--) {
74
+ if (session.variables[i].name === name) {
75
+ objValue = session.variables[i].value;
76
+ break;
77
+ }
78
+ }
79
+ let obj = typeof objValue === 'string' ? JSON.parse(objValue) : objValue;
80
+
81
+ // Simple key access
82
+ if (key !== undefined && key !== '') {
83
+ return obj[key];
84
+ }
85
+
86
+ // Path access (dot notation and array indices)
87
+ if (jsonPath !== undefined && jsonPath !== '') {
88
+ let current = obj;
89
+
90
+ // Parse jsonPath: support "a.b.c" and "items[0].name"
91
+ const parts = jsonPath.match(/([^.\[\]]+)|\[(\d+)\]/g);
92
+
93
+ if (!parts) return undefined;
94
+
95
+ for (const part of parts) {
96
+ if (current === null || current === undefined) {
97
+ return undefined;
98
+ }
99
+
100
+ // Check if it's an array index [0]
101
+ if (part.startsWith('[') && part.endsWith(']')) {
102
+ const idx = parseInt(part.slice(1, -1));
103
+ current = current[idx];
104
+ } else {
105
+ current = current[part];
106
+ }
107
+ }
108
+
109
+ // Return primitive values as-is, objects as JSON strings
110
+ if (typeof current === 'object' && current !== null) {
111
+ return JSON.stringify(current);
112
+ }
113
+ return current;
114
+ }
115
+
116
+ throw new Error('Either key or path parameter required');
117
+ </eval>
118
+ <output><variable name="result" /></output>
119
+ </subroutine>
120
+
121
+ <!-- set: Set value by key -->
122
+ <subroutine name="set" param-key="string:required:object key">
123
+ <defvar name="value"><parameters select="*" /></defvar>
124
+ <eval>
125
+ let objValue;
126
+ let varIndex = -1;
127
+ for (let i = session.variables.length - 1; i >= 0; i--) {
128
+ if (session.variables[i].name === name) {
129
+ objValue = session.variables[i].value;
130
+ varIndex = i;
131
+ break;
132
+ }
133
+ }
134
+ let obj = typeof objValue === 'string' ? JSON.parse(objValue) : objValue;
135
+ if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
136
+ throw new Error(`Variable ${name} is not a JSON object`);
137
+ }
138
+
139
+ obj[key] = value;
140
+
141
+ // Update the variable in place
142
+ if (varIndex >= 0) {
143
+ session.variables[varIndex].value = JSON.stringify(obj);
144
+ }
145
+ return value;
146
+ </eval>
147
+ </subroutine>
148
+
149
+ <!-- has: Check if key exists -->
150
+ <subroutine name="has" param-key="string:required:object key">
151
+ <eval name="result">
152
+ let objValue;
153
+ for (let i = session.variables.length - 1; i >= 0; i--) {
154
+ if (session.variables[i].name === name) {
155
+ objValue = session.variables[i].value;
156
+ break;
157
+ }
158
+ }
159
+ let obj = typeof objValue === 'string' ? JSON.parse(objValue) : objValue;
160
+ if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
161
+ throw new Error(`Variable ${name} is not a JSON object`);
162
+ }
163
+ return obj.hasOwnProperty(key);
164
+ </eval>
165
+ <output><variable name="result" /></output>
166
+ </subroutine>
167
+
168
+ <!-- stringify: Convert to JSON string -->
169
+ <subroutine name="stringify" param-indent="string:optional:indentation (2, 4, etc.)">
170
+ <eval name="result">
171
+ let objValue;
172
+ for (let i = session.variables.length - 1; i >= 0; i--) {
173
+ if (session.variables[i].name === name) {
174
+ objValue = session.variables[i].value;
175
+ break;
176
+ }
177
+ }
178
+ let obj = typeof objValue === 'string' ? JSON.parse(objValue) : objValue;
179
+
180
+ if (indent !== undefined) {
181
+ const indentNum = parseInt(indent) || 2;
182
+ return JSON.stringify(obj, null, indentNum);
183
+ }
184
+ return JSON.stringify(obj);
185
+ </eval>
186
+ <output><variable name="result" /></output>
187
+ </subroutine>
188
+
189
+ <!-- Execute nested operations -->
190
+ <parameters select="*" />
191
+ </subroutine>
192
+
47
193
  <!-- array: Array operations with nested operation tags -->
48
194
  <subroutine name="array" param-name="string:required:array variable name">
49
195
 
@@ -70,7 +216,7 @@
70
216
  <!-- push: Add item to end of array -->
71
217
  <subroutine name="push">
72
218
  <defvar name="value"><parameters select="*" /></defvar>
73
- <eval>
219
+ <eval name="result">
74
220
  let arrValue;
75
221
  let varIndex = -1;
76
222
  for (let i = session.variables.length - 1; i >= 0; i--) {
@@ -91,6 +237,7 @@
91
237
  }
92
238
  return arr.length;
93
239
  </eval>
240
+ <output><variable name="result" /></output>
94
241
  </subroutine>
95
242
 
96
243
  <!-- pop: Remove and return last item from array -->
@@ -148,7 +295,7 @@
148
295
  <!-- unshift: Add item to beginning of array -->
149
296
  <subroutine name="unshift">
150
297
  <defvar name="value"><parameters select="*" /></defvar>
151
- <eval>
298
+ <eval name="result">
152
299
  let arrValue;
153
300
  let varIndex = -1;
154
301
  for (let i = session.variables.length - 1; i >= 0; i--) {
@@ -169,6 +316,7 @@
169
316
  }
170
317
  return arr.length;
171
318
  </eval>
319
+ <output><variable name="result" /></output>
172
320
  </subroutine>
173
321
 
174
322
  <!-- length: Get array length -->
package/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "dirac-json",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "JSON utility library for DIRAC - declarative JSON parsing and access",
5
5
  "type": "module",
6
6
  "main": "lib/index.di",
7
+ "scripts": {
8
+ "test": "node ../dirac/dist/test-runner.js tests"
9
+ },
7
10
  "keywords": [
8
11
  "dirac",
9
12
  "json",
@@ -0,0 +1,41 @@
1
+ # DIRAC JSON Test Suite
2
+
3
+ Unit tests for the dirac-json library.
4
+
5
+ ## Running Tests
6
+
7
+ From the dirac-json directory:
8
+ ```bash
9
+ npm test
10
+ ```
11
+
12
+ ## Test Coverage
13
+
14
+ ### Array Operations
15
+ - ✅ `<array><get>` - Get item at index
16
+ - ✅ `<array><push>` - Add item to end
17
+ - ✅ `<array><pop>` - Remove and return last item
18
+ - ✅ `<array><shift>` - Remove and return first item
19
+ - ✅ `<array><unshift>` - Add item to beginning
20
+ - ✅ `<array><length>` - Get array length
21
+
22
+ ### JSON Object Operations
23
+ - ✅ `<json><getKeys>` - Get object keys as array
24
+ - ✅ `<json><get key="">` - Get value by simple key
25
+ - ✅ `<json><get jsonPath="">` - Get value by path with dot notation
26
+ - ✅ `<json><get jsonPath="">` - Get value by path with array indices
27
+ - ✅ `<json><has>` - Check if key exists
28
+ - ✅ `<json><set>` - Set value by key
29
+ - ✅ `<json><stringify>` - Convert to JSON string
30
+
31
+ ## Test File Format
32
+
33
+ Each test file follows this pattern:
34
+ ```xml
35
+ <!-- TEST: test_name -->
36
+ <!-- EXPECT: expected output -->
37
+ <dirac>
38
+ <import src="../lib/index.di" />
39
+ <!-- test code here -->
40
+ </dirac>
41
+ ```
@@ -0,0 +1,8 @@
1
+ <!-- TEST: array_get -->
2
+ <!-- EXPECT: Item at index 1: banana -->
3
+ <dirac>
4
+ <import src="../lib/index.di" />
5
+ <defvar name="fruits">["apple", "banana", "cherry"]</defvar>
6
+ <defvar name="item"><array name="fruits"><get index="1" /></array></defvar>
7
+ <output>Item at index 1: <variable name="item" /></output>
8
+ </dirac>
@@ -0,0 +1,8 @@
1
+ <!-- TEST: array_length -->
2
+ <!-- EXPECT: Array length: 3 -->
3
+ <dirac>
4
+ <import src="../lib/index.di" />
5
+ <defvar name="fruits">["apple", "banana", "cherry"]</defvar>
6
+ <defvar name="len"><array name="fruits"><length /></array></defvar>
7
+ <output>Array length: <variable name="len" /></output>
8
+ </dirac>
@@ -0,0 +1,8 @@
1
+ <!-- TEST: array_pop -->
2
+ <!-- EXPECT: Popped: cherry -->
3
+ <dirac>
4
+ <import src="../lib/index.di" />
5
+ <defvar name="fruits">["apple", "banana", "cherry"]</defvar>
6
+ <defvar name="last"><array name="fruits"><pop /></array></defvar>
7
+ <output>Popped: <variable name="last" /></output>
8
+ </dirac>
@@ -0,0 +1,8 @@
1
+ <!-- TEST: array_push -->
2
+ <!-- EXPECT: After push: 4 -->
3
+ <dirac>
4
+ <import src="../lib/index.di" />
5
+ <defvar name="fruits">["apple", "banana", "cherry"]</defvar>
6
+ <defvar name="len"><array name="fruits"><push>date</push></array></defvar>
7
+ <output>After push: <variable name="len" /></output>
8
+ </dirac>
@@ -0,0 +1,8 @@
1
+ <!-- TEST: array_shift -->
2
+ <!-- EXPECT: Shifted: apple -->
3
+ <dirac>
4
+ <import src="../lib/index.di" />
5
+ <defvar name="fruits">["apple", "banana", "cherry"]</defvar>
6
+ <defvar name="first"><array name="fruits"><shift /></array></defvar>
7
+ <output>Shifted: <variable name="first" /></output>
8
+ </dirac>
@@ -0,0 +1,8 @@
1
+ <!-- TEST: array_unshift -->
2
+ <!-- EXPECT: After unshift: 4 -->
3
+ <dirac>
4
+ <import src="../lib/index.di" />
5
+ <defvar name="fruits">["apple", "banana", "cherry"]</defvar>
6
+ <defvar name="len"><array name="fruits"><unshift>mango</unshift></array></defvar>
7
+ <output>After unshift: <variable name="len" /></output>
8
+ </dirac>
@@ -0,0 +1,28 @@
1
+ <dirac>
2
+ <import src="../lib/index.di" />
3
+
4
+ <output>Debug path parsing</output>
5
+
6
+ <!-- Test the actual structure -->
7
+ <defvar name="packages">{"dirac-json": ["json", "array"]}</defvar>
8
+ <output>Full packages: <variable name="packages" /></output>
9
+
10
+ <defvar name="val1"><json name="packages"><get key="dirac-json" /></json></defvar>
11
+ <output>Get by key 'dirac-json': <variable name="val1" /></output>
12
+
13
+ <defvar name="val2"><json name="packages"><get jsonPath="dirac-json" /></json></defvar>
14
+ <output>Get by path 'dirac-json': <variable name="val2" /></output>
15
+
16
+ <defvar name="val3"><json name="packages"><get jsonPath="dirac-json[0]" /></json></defvar>
17
+ <output>Get by path 'dirac-json[0]': <variable name="val3" /></output>
18
+
19
+ <!-- Test nested object -->
20
+ <defvar name="nested">{"user": {"name": "Alice"}}</defvar>
21
+ <output>Full nested: <variable name="nested" /></output>
22
+
23
+ <defvar name="val4"><json name="nested"><get jsonPath="user" /></json></defvar>
24
+ <output>Get path 'user': <variable name="val4" /></output>
25
+
26
+ <defvar name="val5"><json name="nested"><get jsonPath="user.name" /></json></defvar>
27
+ <output>Get path 'user.name': <variable name="val5" /></output>
28
+ </dirac>
@@ -0,0 +1,8 @@
1
+ <!-- TEST: json_get_key -->
2
+ <!-- EXPECT: Name: Alice -->
3
+ <dirac>
4
+ <import src="../lib/index.di" />
5
+ <defvar name="person">{"name": "Alice", "age": 30, "city": "NYC"}</defvar>
6
+ <defvar name="name"><json name="person"><get key="name" /></json></defvar>
7
+ <output>Name: <variable name="name" /></output>
8
+ </dirac>
@@ -0,0 +1,8 @@
1
+ <!-- TEST: json_get_path_array -->
2
+ <!-- EXPECT: First hobby: reading -->
3
+ <dirac>
4
+ <import src="../lib/index.di" />
5
+ <defvar name="person">{"name": "Alice", "hobbies": ["reading", "hiking"]}</defvar>
6
+ <defvar name="hobby"><json name="person"><get jsonPath="hobbies[0]" /></json></defvar>
7
+ <output>First hobby: <variable name="hobby" /></output>
8
+ </dirac>
@@ -0,0 +1,8 @@
1
+ <!-- TEST: json_get_path_dot -->
2
+ <!-- EXPECT: Street: Main St -->
3
+ <dirac>
4
+ <import src="../lib/index.di" />
5
+ <defvar name="person">{"name": "Alice", "address": {"street": "Main St", "city": "NYC"}}</defvar>
6
+ <defvar name="street"><json name="person"><get jsonPath="address.street" /></json></defvar>
7
+ <output>Street: <variable name="street" /></output>
8
+ </dirac>
@@ -0,0 +1,8 @@
1
+ <!-- TEST: json_getKeys -->
2
+ <!-- EXPECT: Keys: ["name","age","city"] -->
3
+ <dirac>
4
+ <import src="../lib/index.di" />
5
+ <defvar name="person">{"name": "Alice", "age": 30, "city": "NYC"}</defvar>
6
+ <defvar name="keys"><json name="person"><getKeys /></json></defvar>
7
+ <output>Keys: <variable name="keys" /></output>
8
+ </dirac>
@@ -0,0 +1,8 @@
1
+ <!-- TEST: json_has_key_missing -->
2
+ <!-- EXPECT: Has email: false -->
3
+ <dirac>
4
+ <import src="../lib/index.di" />
5
+ <defvar name="person">{"name": "Alice", "age": 30}</defvar>
6
+ <defvar name="hasEmail"><json name="person"><has key="email" /></json></defvar>
7
+ <output>Has email: <variable name="hasEmail" /></output>
8
+ </dirac>
@@ -0,0 +1,8 @@
1
+ <!-- TEST: json_has_key -->
2
+ <!-- EXPECT: Has name: true -->
3
+ <dirac>
4
+ <import src="../lib/index.di" />
5
+ <defvar name="person">{"name": "Alice", "age": 30}</defvar>
6
+ <defvar name="hasName"><json name="person"><has key="name" /></json></defvar>
7
+ <output>Has name: <variable name="hasName" /></output>
8
+ </dirac>
@@ -0,0 +1,13 @@
1
+ <!-- TEST: json_iteration -->
2
+ <!-- EXPECT_CONTAINS: Package: dirac-json -->
3
+ <!-- EXPECT_CONTAINS: Package: dirac-http -->
4
+ <dirac>
5
+ <import src="../lib/index.di" />
6
+ <defvar name="packages">{"dirac-json": ["json"], "dirac-http": ["http"]}</defvar>
7
+ <defvar name="keys"><json name="packages"><getKeys /></json></defvar>
8
+ <defvar name="count"><array name="keys"><length /></array></defvar>
9
+ <loop count="${count}">
10
+ <defvar name="key"><array name="keys"><get index="${i}" /></array></defvar>
11
+ <output>Package: <variable name="key" /></output>
12
+ </loop>
13
+ </dirac>
@@ -0,0 +1,68 @@
1
+ <!-- Test JSON object operations -->
2
+ <dirac>
3
+ <import src="../lib/index.di" />
4
+
5
+ <output>=== Testing JSON Object Operations ===</output>
6
+
7
+ <!-- Test 1: getKeys -->
8
+ <output>
9
+ Test 1: getKeys</output>
10
+ <defvar name="packages">{"dirac-json": ["json", "array"], "dirac-mongodb": ["mongodb", "database"], "dirac-http": ["http", "rest"]}</defvar>
11
+ <defvar name="keys"><json name="packages"><getKeys /></json></defvar>
12
+ <output>Keys: <variable name="keys" /></output>
13
+
14
+ <!-- Test 2: Simple key access -->
15
+ <output>
16
+ Test 2: Get by key</output>
17
+ <defvar name="jsonValue"><json name="packages"><get key="dirac-json" /></json></defvar>
18
+ <output>dirac-json value: <variable name="jsonValue" /></output>
19
+
20
+ <!-- Test 3: Path with array index -->
21
+ <output>
22
+ Test 3: Get by path with array index</output>
23
+ <defvar name="firstKeyword"><json name="packages"><get jsonPath="dirac-json[0]" /></json></defvar>
24
+ <output>First keyword: <variable name="firstKeyword" /></output>
25
+
26
+ <!-- Test 4: Nested path -->
27
+ <output>
28
+ Test 4: Nested object path</output>
29
+ <defvar name="nestedObj">{"user": {"name": "Alice", "settings": {"theme": "dark"}}}</defvar>
30
+ <defvar name="theme"><json name="nestedObj"><get jsonPath="user.settings.theme" /></json></defvar>
31
+ <output>Theme: <variable name="theme" /></output>
32
+
33
+ <!-- Test 5: has key -->
34
+ <output>
35
+ Test 5: Check if key exists</output>
36
+ <defvar name="hasJson"><json name="packages"><has key="dirac-json" /></json></defvar>
37
+ <defvar name="hasNope"><json name="packages"><has key="nope" /></json></defvar>
38
+ <output>Has dirac-json: <variable name="hasJson" /></output>
39
+ <output>Has nope: <variable name="hasNope" /></output>
40
+
41
+ <!-- Test 6: Iterate over keys -->
42
+ <output>
43
+ Test 6: Iterate over object keys</output>
44
+ <defvar name="pkgKeys"><json name="packages"><getKeys /></json></defvar>
45
+ <defvar name="keyCount"><array name="pkgKeys"><length /></array></defvar>
46
+ <loop count="${keyCount}">
47
+ <defvar name="key"><array name="pkgKeys"><get index="${i}" /></array></defvar>
48
+ <defvar name="value"><json name="packages"><get key="${key}" /></json></defvar>
49
+ <output> Package: <variable name="key" />, Keywords: <variable name="value" /></output>
50
+ </loop>
51
+
52
+ <!-- Test 7: set key -->
53
+ <output>
54
+ Test 7: Set new key</output>
55
+ <json name="packages"><set key="dirac-new">["new", "package"]</set></json>
56
+ <defvar name="updatedKeys"><json name="packages"><getKeys /></json></defvar>
57
+ <output>Updated keys: <variable name="updatedKeys" /></output>
58
+
59
+ <!-- Test 8: stringify -->
60
+ <output>
61
+ Test 8: Stringify with indent</output>
62
+ <defvar name="prettified"><json name="packages"><stringify indent="2" /></json></defvar>
63
+ <output>Pretty JSON:
64
+ <variable name="prettified" /></output>
65
+
66
+ <output>
67
+ === All JSON tests complete! ===</output>
68
+ </dirac>
@@ -0,0 +1,9 @@
1
+ <!-- TEST: json_set_key -->
2
+ <!-- EXPECT: ["name","age","city","email"] -->
3
+ <dirac>
4
+ <import src="../lib/index.di" />
5
+ <defvar name="person">{"name": "Alice", "age": 30, "city": "NYC"}</defvar>
6
+ <json name="person"><set key="email">alice@example.com</set></json>
7
+ <defvar name="keys"><json name="person"><getKeys /></json></defvar>
8
+ <output><variable name="keys" /></output>
9
+ </dirac>
@@ -0,0 +1,8 @@
1
+ <!-- TEST: json_stringify -->
2
+ <!-- EXPECT_CONTAINS: "name": "Alice" -->
3
+ <dirac>
4
+ <import src="../lib/index.di" />
5
+ <defvar name="person">{"name": "Alice", "age": 30}</defvar>
6
+ <defvar name="str"><json name="person"><stringify indent="2" /></json></defvar>
7
+ <output><variable name="str" /></output>
8
+ </dirac>