From 2ca7cc12c9d0cb39e6f041f7275012644a62ecf0 Mon Sep 17 00:00:00 2001 From: Daniel Cazzulino Date: Thu, 30 Sep 2021 00:29:39 -0300 Subject: [PATCH] Allow specifying a replacement value for empty results This allows distinguishing a non-matching query vs a matched value that is actually empty. Fixed #7 --- Devlooped.Json.sln | 2 ++ readme.md | 18 ++++++++++- src/JsonPeek/JsonPeek.cs | 9 ++++++ src/JsonPeek/readme.md | 16 +++++++++- src/JsonPoke/readme.md | 1 - src/Tests/Peek.targets | 64 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 107 insertions(+), 3 deletions(-) diff --git a/Devlooped.Json.sln b/Devlooped.Json.sln index bfb9512..3704f31 100644 --- a/Devlooped.Json.sln +++ b/Devlooped.Json.sln @@ -12,6 +12,8 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{58AD3669-734C-4A6F-B622-9F75D7E903C2}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig + .netconfig = .netconfig + .github\dependabot.yml = .github\dependabot.yml readme.md = readme.md EndProjectSection EndProject diff --git a/readme.md b/readme.md index 0c4dd74..d8dda2b 100644 --- a/readme.md +++ b/readme.md @@ -27,8 +27,9 @@ Parameters: | Parameter | Description | | ----------- | -------------------------------------------------------------------------------------------------------------- | -| Content | Optional `string` parameter. Input/Output.
Specifies the JSON input as a string. | +| Content | Optional `string` parameter.
Specifies the JSON input as a string. | | ContentPath | Optional `ITaskItem` parameter.
Specifies the JSON input as a file path. | +| Empty | Optional `string` parameter.
Value to use as a replacement for empty values matched in JSON. | | Query | Required `string` parameter.
Specifies the [JSONPath](https://goessner.net/articles/JsonPath/) expression. | | Result | Output `ITaskItem[]` parameter.
Contains the results that are returned by the task. | @@ -86,6 +87,21 @@ These item metadata values could be read as MSBuild properties as follows, for e In addition to the explicitly opted in object properties, the entire node is available as raw JSON via the special `_` (single underscore) metadata item. +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 `Empty` value to stand-in for an empty (but successful) matched +result instead, which allow to distinguish both scenarios: + +```xml + + + + + +``` + + ![JsonPoke Icon](assets/img/jsonpoke.png) JsonPoke ============ diff --git a/src/JsonPeek/JsonPeek.cs b/src/JsonPeek/JsonPeek.cs index 238f78d..1c501c2 100644 --- a/src/JsonPeek/JsonPeek.cs +++ b/src/JsonPeek/JsonPeek.cs @@ -19,6 +19,14 @@ public class JsonPeek : Task /// public ITaskItem? ContentPath { get; set; } + /// + /// Specifies an optional value to use as a replacement for + /// empty values matched in JSON. This allows distinguishing + /// non-matching queries versus queries that match nodes but + /// contain an empty value. + /// + public string? Empty { get; set; } + /// /// Specifies the JSONPath query. /// @@ -57,6 +65,7 @@ public override bool Execute() Result = json.SelectTokens(Query) // NOTE: we cannot create items with empty ItemSpec, so skip them entirely. // see https://github.com/dotnet/msbuild/issues/3399 + .Select(x => !string.IsNullOrEmpty(x.ToString()) ? x : Empty) .Where(x => !string.IsNullOrEmpty(x.ToString())) .SelectMany(x => x.AsItems()).ToArray(); diff --git a/src/JsonPeek/readme.md b/src/JsonPeek/readme.md index d619de2..d8a422a 100644 --- a/src/JsonPeek/readme.md +++ b/src/JsonPeek/readme.md @@ -1,7 +1,6 @@ [![Version](https://img.shields.io/nuget/vpre/JsonPeek.svg?color=royalblue)](https://www.nuget.org/packages/JsonPeek) [![Downloads](https://img.shields.io/nuget/dt/JsonPeek.svg?color=green)](https://www.nuget.org/packages/JsonPeek) [![License](https://img.shields.io/github/license/devlooped/json.svg?color=blue)](https://github.com/devlooped/json/blob/main/license.txt) -[![Build](https://github.com/devlooped/json/workflows/build/badge.svg?branch=main)](https://github.com/devlooped/json/actions) Usage: @@ -68,12 +67,27 @@ These item metadata values could be read as MSBuild properties as follows, for e In addition to the explicitly opted in object properties, the entire node is available as raw JSON via the special `_` (single underscore) metadata item. +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 `Empty` value to stand-in for an empty (but successful) matched +result instead, which allow to distinguish both scenarios: + +```xml + + + + + +``` + ## Parameters | Parameter | Description | | ----------- | -------------------------------------------------------------------------------------------------------------- | | Content | Optional `string` parameter.
Specifies the JSON input as a string. | | ContentPath | Optional `ITaskItem` parameter.
Specifies the JSON input as a file path. | +| Empty | Optional `string` parameter.
Value to use as a replacement for empty values matched in JSON. | | Query | Required `string` parameter.
Specifies the [JSONPath](https://goessner.net/articles/JsonPath/) expression. | | Result | Output `ITaskItem[]` parameter.
Contains the results that are returned by the task. | diff --git a/src/JsonPoke/readme.md b/src/JsonPoke/readme.md index 9b199a3..6d5e3d4 100644 --- a/src/JsonPoke/readme.md +++ b/src/JsonPoke/readme.md @@ -1,7 +1,6 @@ [![Version](https://img.shields.io/nuget/vpre/JsonPoke.svg?color=royalblue)](https://www.nuget.org/packages/JsonPoke) [![Downloads](https://img.shields.io/nuget/dt/JsonPoke.svg?color=green)](https://www.nuget.org/packages/JsonPoke) [![License](https://img.shields.io/github/license/devlooped/json.svg?color=blue)](https://github.com/devlooped/json/blob/main/license.txt) -[![Build](https://github.com/devlooped/json/workflows/build/badge.svg?branch=main)](https://github.com/devlooped/json/actions) Usage: diff --git a/src/Tests/Peek.targets b/src/Tests/Peek.targets index 2d9d2a3..ad5db3d 100644 --- a/src/Tests/Peek.targets +++ b/src/Tests/Peek.targets @@ -38,6 +38,70 @@ + + + + { + "hello": "" + } + + $.hello + + + + + + + + + + + + + + + + + + + { + "hello": "" + } + + $.hello + $empty + + + + + + + + + + + + + + + + + + { + "hello": "" + } + + $.foo + + + + + + + + + +