【问题标题】:Pass a JSON string as a command line argument将 JSON 字符串作为命令行参数传递
【发布时间】:2016-03-24 15:05:10
【问题描述】:

我正在尝试使用命令行将 json 字符串传递给 C# 程序。

JSON 字符串如下所示:

{
    "config": {
        "script": {
            "script_name": "test",
            "dir": "D:\\test",
            "destination": "M:\\neu\\test",
            "params": "/b /s /r:3 /w:5"
        }
    }
}

在命令行中它看起来像这样:

{"config":{"script":{"script_name":"test","dir":"D:\\test","destination":"M:\\neu\\test","params":"/b /s /r:3 /w:5"}}}

但如果我只是传递字符串,那么它会被分成几块。但我希望我的程序将其视为一个字符串。

我必须调整我的 JSON 字符串吗?

【问题讨论】:

  • 所有 json 中固有的引号都会混淆内置解析器
  • @Plutonix 是的,他们将被踢出,然后 JSON 解析器不知道如何处理无效字符串
  • 环境解析参数,所以要正确转义:ss64.com/nt/syntax-esc.html

标签: c# json


【解决方案1】:

使用"" 将其声明为字符串,并使用\ 转义另一个",它应该可以工作。

命令行:

"{\"config\":{\"script\":{\"script_name\":\"test\",\"dir\":\"D:\\test\",\"destination\":\"M:\\neu\\test\",\"params\":\"/b /s /r:3 /w:5\"}}}"

【讨论】:

  • 我试过得到.. 'index' 不被识别为内部或外部命令!
  • '{\"config\":{\"script\":{\"script_name\":\"test\",\"dir\":\"D:\\test\",\"destination\":\"M:\\neu\\test\",\"params\":\"/b /s /r:3 /w:5\"}}}' 单引号可能有效
【解决方案2】:

这应该可行:

var jsonString = Environment.CommandLine;

我使用调试器对其进行了如下测试:

        var jsonString = Environment.CommandLine;
        // (*) This correction makes it work, although it is pretty ugly:
        jsonString = jsonString.Split(new string[] { ".exe\" " }, StringSplitOptions.None)[1];
        var obj =   Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(jsonString);

使用 VS2015 调试,不修改 json 输入(甚至不删除行更改)。我使用与您的输入相同的结构:

    public class Script
    {
        public string script_name { get; set; }
        public string dir { get; set; }
        public string destination { get; set; }
        public string @params { get; set; }
    }

    public class Config
    {
        public Script script { get; set; }
    }

    public class RootObject
    {
        public Config config { get; set; }
    }

关于 (*) => 反序列化的问题是 exe 信息以Environment.CommandLine 添加在命令行前面,它像这样“污染” json:jsonString =

"path\to\assembly\name.vshost.exe" {
    "config": {
        "script": {
            "script_name": "test",
            "dir": "D:\\test",
            "destination": "M:\\neu\\test",
            "params": "/b /s /r:3 /w:5"
        }
    }
}

如果有人对此问题有更好的解决方法,请告诉我。

【讨论】:

  • 您可以删除开头“{”字符之前的所有文本,该字符很少用于文件名。或者你可以更聪明一点,从正在执行的程序集中获取完整路径,然后删除引用的版本。
【解决方案3】:

尝试将 JSON 对象保存到文件中,并将文件作为参数传递给您的应用程序。

@Wildcard27: 这是一个实际用例,用于创建用于教师学位应用程序的 Windows 任务。 JSON 只是我正在使用的 DTO 的简单序列化。

当您序列化 JSON 时,只需将其保存到一个空白文件中,并给它一个正确的名称,以便它是唯一的。

    private string CreateTaskConfigurationFile(string taskName, EquipmentEventExtended eventData, string host)
        {
            List<Change> changes = new List<Change>
            {
                new Change(MailConstants.EventName,eventData.EventName),
                new Change(MailConstants.Deadline, eventData.DateTo.Value.ToShortDateString()),
                new Change(MailConstants.EventDetails, eventData.EventDetails),
                new Change(MailConstants.Link,$"{host}/Inventory/Details/{eventData.InventoryId}")
            };

            MailTaskModel mtm = new MailTaskModel
            {
                Body = MailConstants.UpdateTemplate(MailConstants.TaskMailTemplate, changes),
                Subject = "[Reminder] Upcoming Event needs your attention",
                ToAddress = "abcdef@gmail.com",
                IsHtml = true
            };
            var fileName = string.Format(@"E:\{0}.json", taskName);
            using (StreamWriter file = File.CreateText(fileName))
            {
                JsonSerializer js = new JsonSerializer();
                js.Serialize(file, mtm);
            }
            return fileName;
        }

然后您将文件路径作为参数提供给控制台应用程序:

static void Main(string[] args)
        {
            var configFilePath = args[0];
            var mailConfig = LoadConfigurationFile(configFilePath);
            MailManager manager = new MailManager(mailConfig.ToAddress, mailConfig.FromAddress,mailConfig.Subject, mailConfig.Body,mailConfig.IsHtml);
            manager.SendMail();
        }
        private static MailTaskModel LoadConfigurationFile(string configurationFilePath)
        {
            MailTaskModel mailConfig;
            using(var sr = new StreamReader(configurationFilePath))
            {
                string json = sr.ReadToEnd();
                mailConfig = JsonConvert.DeserializeObject<MailTaskModel>(json);
            }
            return mailConfig;
        }

然后你可以使用类似的东西

ConsoleApplication.exe -yourFilePath

我已经删除了对 null 的嘈杂检查等所有内容,以便更清晰。

【讨论】:

  • 你能举个例子吗?
【解决方案4】:

您可以使用Environment.CommandLine,而不是查看“string[] args”。

来自 MSDN https://msdn.microsoft.com/en-us/library/system.environment.commandline.aspx

public static void Main() 
{
   Console.WriteLine();
   //  Invoke this sample with an arbitrary set of command line arguments.
   Console.WriteLine("CommandLine: {0}", Environment.CommandLine);
}

// 该示例显示如下输出: // C:>env0 任意文本 //
// 命令行:env0 任意文本

【讨论】:

  • 这给了我以下信息:\"CURRENT_EXECUTIVE\" {\"config\":{\"script\":{\"script_name\":\"test\",\"dir\":\"D:\\\\test\",\"destination\":\"M:\\\\neu\\\\test\",\"params\":\"/b /s /r:3 /w:5\"}}}" 那么如何提取我的 JSON 字符串?
  • 是的,它将包含实际的 exe 路径。尝试丢弃刚刚超过第二个引号。像json = cmdline.substring(cmdline.IndexOf("\"", 2)) 这样的东西。不确定是否所有的 \" 只是 Visualstudio 的产物。但cmdline.Replace("\\\"", "\"") 应该解决这个问题。
【解决方案5】:

只需在捕获值后将 json 值发送到命令行并替换它。这对我有用。

args[1].Replace("{","{\"").Replace(":","\":\"").Replace(",","\",\"").Replace("}","\"}");

【讨论】:

  • 我认为你在做某事。但是,如果您有一个在冒号后立即包含方括号的 JSON 列表,那么 Replace 需要调整。
【解决方案6】:

继@Selcuk Gurals 的帖子之后,这里有一个更完整的答案:

args[1].Replace("{", "{\"").Replace(":", "\":\"").Replace(",", "\",\"").Replace("}", "\"}").Replace(":\"[", ":[").Replace(":\"{", ":{").Replace("https\":\"", "https:").Replace("http\":\"", "http:").Replace("\":\"9", ":9").Replace("}\",", "},").Replace("]\",", "],").Replace("}\"}", "}}");

这适用于嵌入式 http/https 和端口等内容。我的端口号在 9000 区域...所以正则表达式解决方案会更好。但它改进了前一个答案 JSON键/值对的值部分也可以是:

  1. 另一个 JSON 对象
  2. 列表

"key": {}, ....
"key":[], ....

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-26
    • 1970-01-01
    • 2020-03-09
    • 2017-12-17
    • 2016-09-08
    相关资源
    最近更新 更多