-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
495 lines (391 loc) · 33.4 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,maximum-scale=2">
<link rel="stylesheet" type="text/css" media="screen" href="/json/assets/css/style.css?v=82a487fbf2cb34192bdc1c2e6c70e9e61f78894c">
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>JsonPeek and JsonPoke MSBuild Tasks | json</title>
<meta name="generator" content="Jekyll v3.9.5" />
<meta property="og:title" content="JsonPeek and JsonPoke MSBuild Tasks" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="JsonPeek and JsonPoke tasks implementations" />
<meta property="og:description" content="JsonPeek and JsonPoke tasks implementations" />
<meta property="og:site_name" content="json" />
<meta property="og:type" content="website" />
<meta name="twitter:card" content="summary" />
<meta property="twitter:title" content="JsonPeek and JsonPoke MSBuild Tasks" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"WebSite","description":"JsonPeek and JsonPoke tasks implementations","headline":"JsonPeek and JsonPoke MSBuild Tasks","name":"json","url":"/json/"}</script>
<!-- End Jekyll SEO tag -->
<!-- start custom head snippets, customize with your own _includes/head-custom.html file -->
<!-- Setup Google Analytics -->
<!-- You can set your favicon here -->
<!-- link rel="shortcut icon" type="image/x-icon" href="/json/favicon.ico" -->
<!-- end custom head snippets -->
</head>
<body>
<!-- HEADER -->
<div id="header_wrap" class="outer">
<header class="inner">
<a id="forkme_banner" href="https://github.com/devlooped/json">View on GitHub</a>
<h1 id="project_title">json</h1>
<h2 id="project_tagline">JsonPeek and JsonPoke tasks implementations</h2>
</header>
</div>
<!-- MAIN CONTENT -->
<div id="main_content_wrap" class="outer">
<section id="main_content" class="inner">
<h1 id="-jsonpeek-and-jsonpoke-msbuild-tasks"><img src="/json/assets/img/json.png" alt="JSON Icon" /> JsonPeek and JsonPoke MSBuild Tasks</h1>
<p><a href="https://github.com/devlooped/json/blob/main/license.txt"><img src="https://img.shields.io/github/license/devlooped/json.svg?color=blue" alt="License" /></a>
<a href="https://github.com/devlooped/json/actions"><img src="https://github.com/devlooped/json/workflows/build/badge.svg?branch=main" alt="Build" /></a></p>
<h1 id="-jsonpeek"><img src="/json/assets/img/jsonpeek.png" alt="JsonPeek Icon" /> JsonPeek</h1>
<p><a href="https://www.nuget.org/packages/JsonPeek"><img src="https://img.shields.io/nuget/vpre/JsonPeek.svg?color=royalblue" alt="Version" /></a>
<a href="https://www.nuget.org/packages/JsonPeek"><img src="https://img.shields.io/nuget/dt/JsonPeek.svg?color=green" alt="Downloads" /></a></p>
<!-- #JsonPeek -->
<p>Read values from JSON using JSONPath.</p>
<p>Usage:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><JsonPeek</span> <span class="na">ContentPath=</span><span class="s">"[JSON_FILE]"</span> <span class="na">Query=</span><span class="s">"[JSONPath]"</span><span class="nt">></span>
<span class="nt"><Output</span> <span class="na">TaskParameter=</span><span class="s">"Result"</span> <span class="na">PropertyName=</span><span class="s">"Value"</span> <span class="nt">/></span>
<span class="nt"></JsonPeek></span>
<span class="nt"><JsonPeek</span> <span class="na">Content=</span><span class="s">"[JSON]"</span> <span class="na">Query=</span><span class="s">"[JSONPath]"</span><span class="nt">></span>
<span class="nt"><Output</span> <span class="na">TaskParameter=</span><span class="s">"Result"</span> <span class="na">ItemName=</span><span class="s">"Values"</span> <span class="nt">/></span>
<span class="nt"></JsonPeek></span>
</code></pre></div></div>
<p>Parameters:</p>
<table>
<thead>
<tr>
<th>Parameter</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>Content</td>
<td>Optional <code class="language-plaintext highlighter-rouge">string</code> parameter.<br />Specifies the JSON input as a string.</td>
</tr>
<tr>
<td>ContentPath</td>
<td>Optional <code class="language-plaintext highlighter-rouge">ITaskItem</code> parameter.<br />Specifies the JSON input as a file path.</td>
</tr>
<tr>
<td>Empty</td>
<td>Optional <code class="language-plaintext highlighter-rouge">string</code> parameter.<br />Value to use as a replacement for empty values matched in JSON.</td>
</tr>
<tr>
<td>Query</td>
<td>Required <code class="language-plaintext highlighter-rouge">string</code> parameter.<br />Specifies the <a href="https://goessner.net/articles/JsonPath/">JSONPath</a> expression.</td>
</tr>
<tr>
<td>Result</td>
<td>Output <code class="language-plaintext highlighter-rouge">ITaskItem[]</code> parameter.<br />Contains the results that are returned by the task.</td>
</tr>
</tbody>
</table>
<p>You can either provide the path to a JSON file via <code class="language-plaintext highlighter-rouge">ContentPath</code> or
provide the straight JSON content to <code class="language-plaintext highlighter-rouge">Content</code>. The <code class="language-plaintext highlighter-rouge">Query</code> is a
<a href="https://goessner.net/articles/JsonPath/">JSONPath</a> expression that is evaluated
and returned via the <code class="language-plaintext highlighter-rouge">Result</code> task parameter. You can assign the resulting
value to either a property (i.e. for a single value) or an item name (i.e.
for multiple results).</p>
<p>JSON object properties are automatically projected as item metadata when
assigning the resulting value to an item. For example, given the following JSON:</p>
<pre><code class="language-JSON">{
"http": {
"host": "localhost",
"port": 80,
"ssl": true
}
}
</code></pre>
<p>You can read the entire <code class="language-plaintext highlighter-rouge">http</code> value as an item with each property as a metadata
value with:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><JsonPeek</span> <span class="na">ContentPath=</span><span class="s">"host.json"</span> <span class="na">Query=</span><span class="s">"$.http"</span><span class="nt">></span>
<span class="nt"><Output</span> <span class="na">TaskParameter=</span><span class="s">"Result"</span> <span class="na">ItemName=</span><span class="s">"Http"</span> <span class="nt">/></span>
<span class="nt"></JsonPeek></span>
</code></pre></div></div>
<p>The <code class="language-plaintext highlighter-rouge">Http</code> item will have the following values (if it were declared in MSBuild):</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><ItemGroup></span>
<span class="nt"><Http</span> <span class="na">Include=</span><span class="s">"[item raw json]"</span><span class="nt">></span>
<span class="nt"><host></span>localhost<span class="nt"></host></span>
<span class="nt"><port></span>80<span class="nt"></port></span>
<span class="nt"><ssl></span>true<span class="nt"></ssl></span>
<span class="nt"></Http></span>
<span class="nt"></ItemGroup></span>
</code></pre></div></div>
<p>These item metadata values could be read as MSBuild properties as follows, for example:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><PropertyGroup></span>
<span class="nt"><Host></span>@(Http -> '%(host)')<span class="nt"></Host></span>
<span class="nt"><Port></span>@(Http -> '%(port)')<span class="nt"></Port></span>
<span class="nt"><Ssl></span>@(Http -> '%(ssl)')<span class="nt"></Ssl></span>
<span class="nt"></PropertyGroup></span>
</code></pre></div></div>
<p>In addition to the explicitly opted in object properties, the entire node is available
as raw JSON via the special <code class="language-plaintext highlighter-rouge">_</code> (single underscore) metadata item.</p>
<p>If the matched value is empty, no items (because items cannot be constructed with empty
identity) or property value will be returned. This makes it difficult to distinguish a
successfully matched empty value from no value matched at all. For these cases, it’s
possible to specify an <code class="language-plaintext highlighter-rouge">Empty</code> value to stand-in for an empty (but successful) matched
result instead, which allow to distinguish both scenarios:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><JsonPeek</span> <span class="na">Content=</span><span class="s">"$(Json)"</span> <span class="na">Empty=</span><span class="s">"$empty"</span> <span class="na">Query=</span><span class="s">"$(Query)"</span><span class="nt">></span>
<span class="nt"><Output</span> <span class="na">TaskParameter=</span><span class="s">"Result"</span> <span class="na">PropertyName=</span><span class="s">"Value"</span> <span class="nt">/></span>
<span class="nt"></JsonPeek></span>
<span class="nt"><Error</span> <span class="na">Condition=</span><span class="s">"'$(Value)' == '$empty'"</span> <span class="na">Text=</span><span class="s">"The element $(Query) cannot have an empty value."</span> <span class="nt">/></span>
</code></pre></div></div>
<!-- #JsonPeek -->
<h1 id="-jsonpoke"><img src="/json/assets/img/jsonpoke.png" alt="JsonPoke Icon" /> JsonPoke</h1>
<p><a href="https://www.nuget.org/packages/JsonPoke"><img src="https://img.shields.io/nuget/vpre/JsonPoke.svg?color=royalblue" alt="Version" /></a>
<a href="https://www.nuget.org/packages/JsonPoke"><img src="https://img.shields.io/nuget/dt/JsonPoke.svg?color=green" alt="Downloads" /></a></p>
<!-- #JsonPoke -->
<p>Write values to JSON nodes selected with JSONPath</p>
<p>Usage:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><JsonPoke</span> <span class="na">ContentPath=</span><span class="s">"[JSON_FILE]"</span> <span class="na">Query=</span><span class="s">"[JSONPath]"</span> <span class="na">Value=</span><span class="s">"[VALUE]"</span> <span class="nt">/></span>
<span class="nt"><JsonPoke</span> <span class="na">ContentPath=</span><span class="s">"[JSON_FILE]"</span> <span class="na">Query=</span><span class="s">"[JSONPath]"</span> <span class="na">RawValue=</span><span class="s">"[JSON]"</span> <span class="nt">/></span>
<span class="nt"><JsonPoke</span> <span class="na">Content=</span><span class="s">"[JSON]"</span> <span class="na">Query=</span><span class="s">"[JSONPath]"</span> <span class="na">Value=</span><span class="s">"[VALUE]"</span> <span class="nt">/></span>
</code></pre></div></div>
<p>Parameters:</p>
<table>
<thead>
<tr>
<th>Parameter</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>Content</td>
<td>Optional <code class="language-plaintext highlighter-rouge">string</code> input/output parameter.<br />Specifies the JSON input as a string and contains the updated<br />JSON after successful task execution.</td>
</tr>
<tr>
<td>ContentPath</td>
<td>Optional <code class="language-plaintext highlighter-rouge">ITaskItem</code> parameter.<br />Specifies the JSON input as a file path.</td>
</tr>
<tr>
<td>Query</td>
<td>Required <code class="language-plaintext highlighter-rouge">string</code> parameter.<br />Specifies the <a href="https://goessner.net/articles/JsonPath/">JSONPath</a> expression.</td>
</tr>
<tr>
<td>Value</td>
<td>Optional <code class="language-plaintext highlighter-rouge">ITaskItem[]</code> parameter.<br />Specifies the value(s) to be inserted into the specified path.</td>
</tr>
<tr>
<td>RawValue</td>
<td>Optional <code class="language-plaintext highlighter-rouge">string</code> parameter.<br />Specifies the raw (JSON) value to be inserted into the specified path.</td>
</tr>
</tbody>
</table>
<p>You must either provide the path to a JSON file via <code class="language-plaintext highlighter-rouge">ContentPath</code> or
raw JSON content via <code class="language-plaintext highlighter-rouge">Content</code>.</p>
<p>The <code class="language-plaintext highlighter-rouge">Value</code> can be an item group, and in that case, it will be inserted into the
JSON node matching the <a href="https://goessner.net/articles/JsonPath/">JSONPath</a> expression
<code class="language-plaintext highlighter-rouge">Query</code> as an array. <code class="language-plaintext highlighter-rouge">RawValue</code> can be used to provide
an entire JSON fragment as a string, with no conversion to an MSBuild item at all.</p>
<p>The existing JSON node will determine the data type of the value being written,
so as to preserve the original document. Numbers, booleans and DateTimes are
properly parsed before serializing to the node.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><PropertyGroup></span>
<span class="nt"><Json></span>
{
"http": {
"host": "localhost",
"port": 80,
"ssl": true
}
}
<span class="nt"></Json></span>
<span class="nt"></PropertyGroup></span>
<span class="nt"><JsonPoke</span> <span class="na">Content=</span><span class="s">"$(Json)"</span> <span class="na">Query=</span><span class="s">"$.http.host"</span> <span class="na">Value=</span><span class="s">"example.com"</span><span class="nt">></span>
<span class="nt"><Output</span> <span class="na">TaskParameter=</span><span class="s">"Content"</span> <span class="na">PropertyName=</span><span class="s">"Json"</span> <span class="nt">/></span>
<span class="nt"></JsonPoke></span>
<span class="nt"><JsonPoke</span> <span class="na">Content=</span><span class="s">"$(Json)"</span> <span class="na">Query=</span><span class="s">"$.http.port"</span> <span class="na">Value=</span><span class="s">"80"</span><span class="nt">></span>
<span class="nt"><Output</span> <span class="na">TaskParameter=</span><span class="s">"Content"</span> <span class="na">PropertyName=</span><span class="s">"Json"</span> <span class="nt">/></span>
<span class="nt"></JsonPoke></span>
<span class="nt"><JsonPoke</span> <span class="na">Content=</span><span class="s">"$(Json)"</span> <span class="na">Query=</span><span class="s">"$.http.ssl"</span> <span class="na">Value=</span><span class="s">"true"</span><span class="nt">></span>
<span class="nt"><Output</span> <span class="na">TaskParameter=</span><span class="s">"Content"</span> <span class="na">PropertyName=</span><span class="s">"Json"</span> <span class="nt">/></span>
<span class="nt"></JsonPoke></span>
<span class="nt"><Message</span> <span class="na">Importance=</span><span class="s">"high"</span> <span class="na">Text=</span><span class="s">"$(Json)"</span> <span class="nt">/></span>
</code></pre></div></div>
<p>Note how we update multiple values and assign the updated content to the
same <code class="language-plaintext highlighter-rouge">$(Json)</code> property so it can be used in subsequent updates. The last
<code class="language-plaintext highlighter-rouge">Message</code> task will render the following JSON:</p>
<pre><code class="language-JSON">{
"http": {
"host": "example.com",
"port": 80,
"ssl": true
}
}
</code></pre>
<blockquote>
<p>NOTE: The port number was preserved as a number, as is the <code class="language-plaintext highlighter-rouge">ssl</code> boolean.</p>
</blockquote>
<p>To force a value to be interpreted as a string, you can surround it with double or single quotes.
For example, given the following JSON file:</p>
<pre><code class="language-JSON">{
"http": {
"ports": [
"80"
]
}
}
</code></pre>
<p>We can replace the <code class="language-plaintext highlighter-rouge">ports</code> array with string values as follows (without the
explicit quotes, the values would be interpreted as numbers otherwise):</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><ItemGroup></span>
<span class="nt"><HttpPort</span> <span class="na">Include=</span><span class="s">"'8080'"</span> <span class="nt">/></span>
<span class="nt"><HttpPort</span> <span class="na">Include=</span><span class="s">"'1080'"</span> <span class="nt">/></span>
<span class="nt"></ItemGroup></span>
<span class="nt"><JsonPoke</span> <span class="na">ContentPath=</span><span class="s">"http.json"</span> <span class="na">Query=</span><span class="s">"$.http.ports"</span> <span class="na">Value=</span><span class="s">"@(HttpPort)"</span> <span class="nt">/></span>
</code></pre></div></div>
<p>Result:</p>
<pre><code class="language-JSON">{
"http": {
"ports": [
"8080",
"1080"
]
}
}
</code></pre>
<p>It’s also possible to write a complex object based on MSBuild item metadata:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><ItemGroup></span>
<span class="nt"><Http</span> <span class="na">Include=</span><span class="s">"Value"</span><span class="nt">></span>
<span class="nt"><host></span>localhost<span class="nt"></host></span>
<span class="nt"><port></span>80<span class="nt"></port></span>
<span class="nt"><ssl></span>true<span class="nt"></ssl></span>
<span class="nt"></Value></span>
<span class="nt"></ItemGroup></span>
<span class="nt"><JsonPoke</span> <span class="na">ContentPath=</span><span class="s">"http.json"</span> <span class="na">Query=</span><span class="s">"$.http"</span> <span class="na">Value=</span><span class="s">"@(Http)"</span> <span class="na">Properties=</span><span class="s">"host;port;ssl"</span> <span class="nt">/></span>
</code></pre></div></div>
<p>Result:</p>
<pre><code class="language-JSON">{
"http": {
"host": "localhost",
"port": 80,
"ssl": true
}
}
</code></pre>
<p>Note how the native JSON type was automatically inferred, even though everything is
basically a string in MSBuild. As noted above, you can surround any of the item metadata
values in double or single quotes to force them to be written as strings instead.</p>
<p>The task can create entire object hierarchies if any segment of the path expression is
not found, which makes it very easy to create complex structures by assigning a single
value. For example, if the <code class="language-plaintext highlighter-rouge">http</code> section in the examples above didn’t exist at all,
the following task would add it automatically, prior to assigning the <code class="language-plaintext highlighter-rouge">ssl</code> property to <code class="language-plaintext highlighter-rouge">true</code>:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><JsonPoke</span> <span class="na">ContentPath=</span><span class="s">"http.json"</span> <span class="na">Query=</span><span class="s">"$.http.ssl"</span> <span class="na">Value=</span><span class="s">"true"</span> <span class="nt">/></span>
</code></pre></div></div>
<p>This also works for indexed queries, such as adding launch profile to
<a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-6.0#lsj">launchSettings.json</a>
by simply assigning a value:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><JsonPoke</span> <span class="na">ContentPath=</span><span class="s">"Properties\launchSettings.json"</span> <span class="na">Query=</span><span class="s">"$.profiles['IIS Express'].commandName"</span> <span class="na">Value=</span><span class="s">"IISExpress"</span> <span class="nt">/></span>
</code></pre></div></div>
<p>which would create the following entry:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="nl">"profiles"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"IIS Express"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"commandName"</span><span class="p">:</span><span class="w"> </span><span class="s2">"IISExpress"</span><span class="p">,</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>Array index is also supported as part of the query, to modify existing values. If the array is empty
or non-existent, it’s also possible to just use the index <code class="language-plaintext highlighter-rouge">[0]</code> to denote the new node should be the
sole element in the new array, like for adding a new watch file value to
<a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-host-json">host.json</a>:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><JsonPoke</span> <span class="na">ContentPath=</span><span class="s">"host.json"</span> <span class="na">Query=</span><span class="s">"$.watchFiles[0]"</span> <span class="na">Value=</span><span class="s">"myFile.txt"</span> <span class="nt">/></span>
</code></pre></div></div>
<p>Which results in:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="err">...</span><span class="w">
</span><span class="nl">"watchFiles"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="s2">"myFile.txt"</span><span class="w"> </span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>It’s quite common to want to add entries to an existing array, usually at the end of the array. The
JSONPath syntax supports indexes that start from the end of the array (such as <code class="language-plaintext highlighter-rouge">[-1:]</code>), but if the
array had any values already, that would match whichever is the last element, meaning in an <em>update</em>
to that element’s value. Since we need a different syntax for <em>inserting</em> a new node, starting from
the end of the list, we leverage the C# syntax <code class="language-plaintext highlighter-rouge">^n</code> where <code class="language-plaintext highlighter-rouge">n</code> is the position starting from the end.
To add a new element at the end of the list, the index <code class="language-plaintext highlighter-rouge">[^1]</code> can be used. <code class="language-plaintext highlighter-rouge">^2</code> means prior to last
and so on.</p>
<p>For example, to <em>add</em> a new watched file to the array in the example above, we could use:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><JsonPoke</span> <span class="na">ContentPath=</span><span class="s">"host.json"</span> <span class="na">Query=</span><span class="s">"$.watchFiles[^1]"</span> <span class="na">Value=</span><span class="s">"myOtherFile.txt"</span> <span class="nt">/></span>
</code></pre></div></div>
<p>Given an existing <code class="language-plaintext highlighter-rouge">host.json</code> file like the one above, we would get a new file added like so:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="err">...</span><span class="w">
</span><span class="nl">"watchFiles"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="s2">"myFile.txt"</span><span class="p">,</span><span class="w"> </span><span class="s2">"myOtherFile.txt"</span><span class="w"> </span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>If the <code class="language-plaintext highlighter-rouge">watchFiles</code> property didn’t exit at all or had no elements, the result would be
the same as if we used <code class="language-plaintext highlighter-rouge">[0]</code>, but this makes the code more flexible if needed.</p>
<p>The modified JSON nodes can be assigned to an item name using the <code class="language-plaintext highlighter-rouge">Result</code> task property,
and will contain the item path (matching the <code class="language-plaintext highlighter-rouge">Query</code> plus the index if multiple nodes were modified)
as well as the <code class="language-plaintext highlighter-rouge">Value</code> item metadata containing the raw JSON that was written.</p>
<!-- #JsonPoke -->
<h1 id="dogfooding">Dogfooding</h1>
<p><a href="https://pkg.kzu.io/index.json"><img src="https://img.shields.io/endpoint?url=https://shields.kzu.io/vpre/JsonPeek/main&label=nuget.ci&color=brightgreen" alt="CI Version" /></a>
<a href="https://github.com/devlooped/json/actions"><img src="https://github.com/devlooped/json/workflows/build/badge.svg?branch=main" alt="Build" /></a></p>
<p>We also produce CI packages from branches and pull requests so you can dogfood builds as quickly as they are produced.</p>
<p>The CI feed is <code class="language-plaintext highlighter-rouge">https://pkg.kzu.io/index.json</code>.</p>
<p>The versioning scheme for packages is:</p>
<ul>
<li>PR builds: <em>42.42.42-pr</em><code class="language-plaintext highlighter-rouge">[NUMBER]</code></li>
<li>Branch builds: <em>42.42.42-</em><code class="language-plaintext highlighter-rouge">[BRANCH]</code>.<code class="language-plaintext highlighter-rouge">[COMMITS]</code></li>
</ul>
<!-- include https://github.com/devlooped/sponsors/raw/main/footer.md -->
<h1 id="sponsors">Sponsors</h1>
<!-- sponsors.md -->
<p><a href="https://github.com/clarius"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/clarius.png" alt="Clarius Org" title="Clarius Org" /></a>
<a href="https://github.com/KirillOsenkov"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/KirillOsenkov.png" alt="Kirill Osenkov" title="Kirill Osenkov" /></a>
<a href="https://github.com/MFB-Technologies-Inc"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/MFB-Technologies-Inc.png" alt="MFB Technologies, Inc." title="MFB Technologies, Inc." /></a>
<a href="https://github.com/decriptor"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/decriptor.png" alt="Stephen Shaw" title="Stephen Shaw" /></a>
<a href="https://github.com/torutek-gh"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/torutek-gh.png" alt="Torutek" title="Torutek" /></a>
<a href="https://github.com/drivenet"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/drivenet.png" alt="DRIVE.NET, Inc." title="DRIVE.NET, Inc." /></a>
<a href="https://github.com/AshleyMedway"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/AshleyMedway.png" alt="Ashley Medway" title="Ashley Medway" /></a>
<a href="https://github.com/Keflon"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/Keflon.png" alt="Keith Pickford" title="Keith Pickford" /></a>
<a href="https://github.com/tbolon"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/tbolon.png" alt="Thomas Bolon" title="Thomas Bolon" /></a>
<a href="https://github.com/kfrancis"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/kfrancis.png" alt="Kori Francis" title="Kori Francis" /></a>
<a href="https://github.com/twenzel"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/twenzel.png" alt="Toni Wenzel" title="Toni Wenzel" /></a>
<a href="https://github.com/Giorgi"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/Giorgi.png" alt="Giorgi Dalakishvili" title="Giorgi Dalakishvili" /></a>
<a href="https://github.com/unoplatform"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/unoplatform.png" alt="Uno Platform" title="Uno Platform" /></a>
<a href="https://github.com/dansiegel"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/dansiegel.png" alt="Dan Siegel" title="Dan Siegel" /></a>
<a href="https://github.com/rbnswartz"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/rbnswartz.png" alt="Reuben Swartz" title="Reuben Swartz" /></a>
<a href="https://github.com/jfoshee"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/jfoshee.png" alt="Jacob Foshee" title="Jacob Foshee" /></a>
<a href="https://github.com/eajhnsn1"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/Mrxx99.png" alt="" title="")](https://github.com/Mrxx99)
[![Eric Johnson](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/eajhnsn1.png "Eric Johnson" /></a>
<a href="https://github.com/IxTechnologies"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/IxTechnologies.png" alt="Ix Technologies B.V." title="Ix Technologies B.V." /></a>
<a href="https://github.com/davidjenni"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/davidjenni.png" alt="David JENNI" title="David JENNI" /></a>
<a href="https://github.com/Jonathan-Hickey"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/Jonathan-Hickey.png" alt="Jonathan " title="Jonathan " /></a>
<a href="https://github.com/okyrylchuk"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/okyrylchuk.png" alt="Oleg Kyrylchuk" title="Oleg Kyrylchuk" /></a>
<a href="https://github.com/akunzai"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/akunzai.png" alt="Charley Wu" title="Charley Wu" /></a>
<a href="https://github.com/jakobt"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/jakobt.png" alt="Jakob Tikjøb Andersen" title="Jakob Tikjøb Andersen" /></a>
<a href="https://github.com/seanalexander"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/seanalexander.png" alt="Seann Alexander" title="Seann Alexander" /></a>
<a href="https://github.com/tinohager"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/tinohager.png" alt="Tino Hager" title="Tino Hager" /></a>
<a href="https://github.com/ploeh"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/ploeh.png" alt="Mark Seemann" title="Mark Seemann" /></a>
<a href="https://github.com/KenBonny"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/KenBonny.png" alt="Ken Bonny" title="Ken Bonny" /></a>
<a href="https://github.com/SimonCropp"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/SimonCropp.png" alt="Simon Cropp" title="Simon Cropp" /></a>
<a href="https://github.com/agileworks-eu"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/agileworks-eu.png" alt="agileworks-eu" title="agileworks-eu" /></a>
<a href="https://github.com/sorahex"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/sorahex.png" alt="sorahex" title="sorahex" /></a>
<a href="https://github.com/arsdragonfly"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/arsdragonfly.png" alt="Zheyu Shen" title="Zheyu Shen" /></a>
<a href="https://github.com/vezel-dev"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/vezel-dev.png" alt="Vezel" title="Vezel" /></a>
<a href="https://github.com/ChilliCream"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/ChilliCream.png" alt="ChilliCream" title="ChilliCream" /></a>
<a href="https://github.com/4OTC"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/4OTC.png" alt="4OTC" title="4OTC" /></a></p>
<!-- sponsors.md -->
<p><a href="https://github.com/sponsors/devlooped"><img src="https://raw.githubusercontent.com/devlooped/sponsors/main/sponsor.png" alt="Sponsor this project" title="Sponsor this project" /></a>
</p>
<p><a href="https://github.com/sponsors">Learn more about GitHub Sponsors</a></p>
<!-- https://github.com/devlooped/sponsors/raw/main/footer.md -->
</section>
</div>
<!-- FOOTER -->
<div id="footer_wrap" class="outer">
<footer class="inner">
<p class="copyright">json maintained by <a href="https://github.com/devlooped">devlooped</a></p>
<p>Published with <a href="https://pages.github.com">GitHub Pages</a></p>
</footer>
</div>
</body>
</html>