Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: how could I read a raw json content #1755

Closed
Tracked by #1758
WeihanLi opened this issue Jun 5, 2022 · 6 comments
Closed
Tracked by #1758

Question: how could I read a raw json content #1755

WeihanLi opened this issue Jun 5, 2022 · 6 comments
Labels
question Further information is requested

Comments

@WeihanLi
Copy link

WeihanLi commented Jun 5, 2022

I'm trying to read raw JSON text as an option value, but no luck finding an effective way

For example:

[Theory]
[InlineData(@"--raw {""Id"":1,""Name"":""Test""}")]
[InlineData(@"--raw {""""Id"""":1,""""Name"""":""""Test""""}")]
[InlineData(@"--raw '{""Id"":1,""Name"":""Test""}'")]
public void SplitTest(string commandLine)
{
    var args = CommandLineStringSplitter.Instance.Split(commandLine).ToArray();
    Assert.Equal(2, args.Length);
    Assert.Equal("--raw", args[0]);
    Assert.Equal(@"{""Id"":1,""Name"":""Test""}", args[1]);
}

All the cases failed, is there a simple way to read raw json text

@WeihanLi WeihanLi changed the title Question: how could I pass a raw json content Question: how could I read a raw json content Jun 5, 2022
@jonsequitur
Copy link
Contributor

The string splitter is intended to emulate the behavior of the command line splitter that prepares the arguments passed to Main(string[] args). From a user's perspective, this behavior will vary even further depending on which shell they use, e.g. cmd.exe versus PowerShell will need different approaches for escaping quotes. Throwing JSON into the mix makes things even more complicated and hard for users to understand even assuming they figure out how to escape everything correctly.

There's a related discussion here: #1740. Using the example program from this comment, here's what your examples produce (assuming I got the escaping right):

image

This is with PowerShell. The first two aren't valid PowerShell and the program never even gets invoked. The last one works because the surrounding single quotes are valid escapes in PowerShell, but CommandLineStringSplitter doesn't take them into account, by design.

In cmd.exe the same command lines do this:

image

None of these survive as valid JSON.

So I would ask a different question: How do you expect your users to write raw JSON content?

@elgonzo
Copy link
Contributor

elgonzo commented Jun 6, 2022

@jonsequitur,

The string splitter is intended to emulate the behavior of the command line splitter that prepares the arguments passed to Main(string[] args)

But it doesn't with respect to escaping of double quotes. I don't know with certainty if the intent of the question is whether the CommandLineSplitter.Split method supports escaping of double quotes in some way, but i tend to belive so; the code in the question showing attempts to find some working escaping scheme for the double quotes implies to me the question is how to escape double quotes as part of argument values so they survive the CommandLineSplitter.Split method. But with respect to escaping double quotes CommandLineSplitter.Split does not emulate the escaping scheme that works in cmd.exe nor that which is working in PS.


Background:

It is possible both in cmd.exe and in Powershell to escape/quote the json string in such a manner that the quotes that form part of the value survive and are passed properly into the args array of the Main method.

Given this very simple console application:

        static void Main(string[] args)
        {
            foreach (var a in args)
                Console.WriteLine($">{a}<");
        }

entering in a cmd.exe shell:

ConsoleApp1 --raw {\"Id\":1,\"Name\":\"Test\"}

will output:

>--raw<
>{"Id":1,"Name":"Test"}<

Note how the double quotes are surviving. CommandLineSplitter does not emulate this cmd.exe escaping scheme.

And entering in PS:

.\ConsoleApp1 --raw '{\"Id\":1,\"Name\":\"Test\"}'

will again yield the output:

>--raw<
>{"Id":1,"Name":"Test"}<

And CommandLineSplitter does not emulate this PS escaping scheme either.

@jonsequitur
Copy link
Contributor

Keep in mind that during command line invocation of your app, CommandLineStringSplitter is not used.

The main goal of the CommandLineStringSplitter is to support completions and testing, though unless we add several shell-specific implementations, there's no way to accommodate these differences in quote escaping.

If you want to assume that your users will correctly escape JSON in order to pass it to your application, it's more correct to test using a string array, e.g.:

var result = parser.Parse(new string[] { "--raw", @"{""Id"":1,""Name"":""Test""}");

@elgonzo
Copy link
Contributor

elgonzo commented Jun 6, 2022

The main goal of the CommandLineStringSplitter is to support completions and testing, though unless we add several shell-specific implementations, there's no way to accommodate these differences in quote escaping.

CommandLineStringSplitter is also used in the Invoke/Parse methods that accept a single string. And it would perhaps be good if the API documentation would make note of the fact that it does not support escaping of double quotes or other characters. Currently, the API documentation for these (extension) methods has only a simple statement: "The command line string input will be split into tokens as if it had been passed on the command line." which omits the fact that there are limits to when this statement is true or not. (Let me know if i should move this to its own topic/issue.)

@WeihanLi
Copy link
Author

WeihanLi commented Jun 7, 2022

How do you expect your users to write raw JSON content?

I'm not sure the users would use which shell. For me, I usually use pwsh on windows, sometimes bash on linux.

Wondering if we could provide a cross-shell implementation so that the users could use consistent scripts across different shells

@jonsequitur
Copy link
Contributor

jonsequitur commented Jun 7, 2022

I'm not sure the users would use which shell. For me, I usually use pwsh on windows, sometimes bash on linux.

@WeihanLi Exactly. And each user will need to handle their own shell-specific escaping to successfully pass a raw JSON string on the command line. Any working example will necessarily be shell-specific. Your example test is also shell-specific.

So yes, it might make sense to create different implementations of CommandLineStringSplitter to mimic the behaviors of different shells. I could see this being useful for testing and, in some cases, for completions.

CommandLineStringSplitter is also used in the Invoke/Parse methods that accept a single string.

@elgonzo While CommandLineStringSplitter is used in those Parse and Invoke overloads, the occasions on which someone will call them are necessarily going to be specialized and, as with shells, the escaping is expected to be handled prior to the call to Split.

Feel free to open another issue for this. I went ahead and opened #1758 .

@jonsequitur jonsequitur added the question Further information is requested label Jun 14, 2022
@dotnet dotnet locked and limited conversation to collaborators Apr 19, 2023
@jonsequitur jonsequitur converted this issue into discussion #2176 Apr 19, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants