Skip to content

Conversation

@daxian-dbw
Copy link
Member

@daxian-dbw daxian-dbw commented Jan 18, 2019

Fixes #8123

PR Summary

We have the public API JsonObject.ConvertFromJson to convert from JSON string in the PowerShell context. It would be good to have a public API for conversion to JSON. This PR refactors the ConvertTo-Json cmdlet to move the core implementation to JsonObject.ConvertToJson, and make ConvertTo-Json call that public method.

This would help the Azure Function PowerShell worker. Currently, we depends on calling the cmdlet to convert object to JSON which is expensive. Once we have the public method JsonObject.ConvertToJson exposed, we can call the API directly to avoid a command invocation.

PR Context

PR Checklist

@daxian-dbw daxian-dbw added the CL-General Indicates that a PR should be marked as a general cmdlet change in the Change Log label Jan 18, 2019
@iSazonov
Copy link
Collaborator

@daxian-dbw I see most of code is simply copy-pasted. It seems old code is not ideal - should we review line by line in depth or only new API?

@daxian-dbw
Copy link
Member Author

daxian-dbw commented Jan 18, 2019

@iSazonov This PR is purely a change on how code is organized, in order to expose the convert-to-json functionality through a public API similar to the existing JsonObject.ConvertFromJson. Updating old code to make it better/faster is not a goal.

When reviewing the changes, I suggest to focus on the new APIs, how ConvertToJsonCommand is changed to depend on JsonObject, and how ConvertToJsonContext is used within JsonObject. Thanks!

targetCmdlet: this);

string output = JsonObject.ConvertToJson(objectToProcess, in context);
if (output != null)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need to check this?

Copy link
Member Author

@daxian-dbw daxian-dbw Jan 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe so. In case ctrl+c is signaled, JsonObject.ConvertToJson would return null, and I think we don't want to write that null to pipeline.
I know that when the pipeline is stopping, WriteObject will throw from MshCommandRuntime._WriteObjectSkipAllowCheck, so technically it might be OK to remove this check.
But I want to play safe here. What do you think?

For comparison, please take a look at the use of Stopping in the original code path where a StopException is thrown which results in return from EndProcessing.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that new code keep previous behavior and my thoughts was "is it useful to return null?" like $null | ConvertTo-Json | Should -Be $null

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, if we want to change that behavior, we should change the code here. JsonObject.ConvertToJson returns null only if StopException is thrown, and it has nothing to do with enabling $null | ConvertTo-Json.

Yeah, $null | ConvertTo-Json seems like a reasonable scenario, but the test should be $null | ConvertTo-Json | Should -Be "null". It's better to discuss this in a separate issue. Can you open an issue?

PS:30> [Newtonsoft.Json.JsonConvert]::SerializeObject($null) -eq "null"
True

Copy link
Collaborator

@iSazonov iSazonov Jan 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you open an issue?

I think @markekraus could comment. If he will confirm that the scenario is useful we'll open new issue.

Copy link
Contributor

@markekraus markekraus Jan 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You never want ConvertTo-Json write $null to the pipeline. But looking at this, the only scenario that would do that is a stopping exception. I'm not sure if there is any edge case where JsonConvert.SerializeObejct() would return a null string object, nothing I have tried to create such a scenario works anyway. It may be safe to remove it, but, I think it's safer to leave it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@markekraus Thanks!

@daxian-dbw I think we need a test for $null | ConvertTo-Json.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$null | ConvertTo-Json is not supported today -- the passed-in $null is ignored. Whether or not we should change the current behavior to support it should be a separate issue.

return obj;

return dict;
cancellationSource.Cancel();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add tests for this?
(I'd not want.)

Copy link
Member Author

@daxian-dbw daxian-dbw Jan 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be difficult to mimic 'ctrl+c' in the test. I have manually tested it though :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SteveL-MSFT added such tests previously and they looks tricky. I don't like this but should ask :-)

Copy link
Contributor

@xtqqczze xtqqczze Jan 19, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is already a test for StopProcessing in test\powershell\Modules\Microsoft.PowerShell.Utility\ConvertTo-Json.Tests.ps1. It is not currently working perfectly, see #8645.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See also: #8593

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @xtqqczze , I will take a look at those two PRs.

@TravisEz13 TravisEz13 added Review - Committee The PR/Issue needs a review from the PowerShell Committee Committee-Reviewed PS-Committee has reviewed this and made a decision and removed Review - Committee The PR/Issue needs a review from the PowerShell Committee labels Jan 23, 2019
@TravisEz13 TravisEz13 merged commit c606b1c into PowerShell:master Jan 23, 2019
@daxian-dbw daxian-dbw deleted the jsonobj branch January 23, 2019 19:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CL-General Indicates that a PR should be marked as a general cmdlet change in the Change Log Committee-Reviewed PS-Committee has reviewed this and made a decision

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose ConvertToJson as an API

5 participants