【问题标题】:passing JSON string via command line通过命令行传递 JSON 字符串
【发布时间】:2015-03-09 10:40:55
【问题描述】:

我将一个对象序列化为 json 字符串并通过命令行将其传递给应用程序,但是当我在应用程序中收到参数时,这不再是 json 字符串而是常规字符串。

我正在使用下面的代码来创建 json 字符串

var jsonStr = new JavaScriptSerializer().Serialize(obj);

我传递的字符串 - "{"name":"abc","place":"xyz"}"
我收到的字符串 - "{name:abc,place:xyz}";

如何维护json字符串的结构?

【问题讨论】:

  • 没有 json 字符串这样的东西。只有字符串。 相关代码在哪里。即命令行,你如何解析它?您在创建命令行之前是否对引号进行了转义?命令行参数的原始值是多少? BTW JavascriptSerializer 是一个不再使用的遗留类,甚至 ASP.NET 使用 Json.NET
  • 来自 json 字符串,我的意思是具有 json 结构的字符串,当您将对象序列化为 json 时得到。
  • 同样,没有区别或需要特殊处理。如果您有问题,那是因为您传递的原始字符串不是您认为传递的字符串 - 您忘记对引号进行编码或者没有引号开始。您使用的命令行是什么,args 项的值是什么?
  • 如果你想将一个 json 字符串从一个命令行程序传递到另一个,你可以通过管道将第一个程序的输出传递给第二个程序,例如 first.exe|second.exe 并将第二个程序更改为从控制台读取Console.ReadToEnd()。您不必转义或编码字符串并且脚本会更干净

标签: c# json cmd


【解决方案1】:

我猜双引号被删除了,因为它们在 CLI 世界中有意义。

我会说将整个 JSON 转换为 base 64 字符串,然后在 CLI 内部再次转换为常规字符串应该可以工作:

var jsonStr = Convert.ToBase64String(Encoding.UTF8.GetBytes(new JavaScriptSerializer().Serialize(obj)));

// When your receive the whole string....
var jsonStr = Encoding.UTF8.GetString(Convert.FromBase64String(inputStr));

// Now deserialize your JSON string into a regular .NET object...

回答@Panagiotis Kanavos 的一些评论...

CLI 不会破坏任何字符串 - 人们现在应该已经注意到了。 如果 OP 发送不同的字符串,则问题出在该代码中,而不是 命令行界面

正如我在 cmets 中指出的那样,我知道在 .NET 世界中我们不需要转义 JSON,也许在其他环境中也不需要这样做。

我建议使用 base 64 方法,因为它是一种防弹解决方案,并且由于 OP 提供的细节很少且代码示例不足,归根结底,我相信 base 64 方法与转义双引号一样有效,但它也提供了一个附加值:它可以转义除" 之外的任何特殊字符。

顺便说一句,在某些实际情况下,CLI 会阻止某些字符。 Windows 上的redis-cli 不允许使用大括号...

更新 2

由于@Panagiotis Kanavos 将 CLI 与 通用语言界面 混淆了,我想确保阅读我答案的每个人都将 CLI 理解为 命令行界面

【讨论】:

  • .NET 中的双引号没有问题。在编写字符串文字时,必须将它们转义,但这里不是这种情况。 JSon 在 .NET 中被广泛使用,尤其是在 ASP.NET MVC 中,无需借助 Base64
  • @PanagiotisKanavos 无论如何,我都知道,但是由于 OP 没有提供有关 CLI 的实际代码或它在他/她的环境中的实际工作方式,我需要提供一个防弹解决方案.
  • 此代码将返回原始字符串。它对这个问题有什么帮助?
  • @PanagiotisKanavos 嘿,用你的头脑(就像李小龙一样!)。它有助于在 CLI 中“按原样”接收字符串!问题是 OP 在目标环境(CLI)中获取到正确的 JSON 后没有收到正确的 JSON
  • @PanagiotisKanavos 显然,所谓的字符串被 CLI 破坏了。我怀疑 CLI 会损坏 base 64 字符串,因为它包含数字和字母,以及 = 符号...
【解决方案2】:

只需用反斜杠转义引号,这样 CMD 就不会删除 JSON 中的引号。

应该传递的字符串:

"{\"name\":\"abc\",\"place\":\"xyz\"}"

将要接收的字符串:

{"name":"abc","place":"xyz"}

使用此代码转义字符串:

string jsonString = new JavaScriptSerializer().Serialize(obj);
string escapedString = jsonString.Replace("\"", "\\\"");

【讨论】:

  • 导致问题的不是 CLI,而是 CMD(命令行)。 CMD also 使用反斜杠,所以这可以工作
  • 同意。修正了答案。
  • @YohDeadfall 由于一些 Panagiotis 评论......我发现他将 CLI 称为“通用语言界面”,我相信你和我都在谈论“命令行界面”如果我们在这个问答中提到了“CLI”,哈哈
  • 是的,CLI 在这个问题中表示命令行界面。但我用 CMD 替换它更清楚:)
  • 我完全无法理解这一点,因为如果我在谈论如何实现一种新的 .NET 语言或类似的东西的话,我会把 CLI 作为公共语言基础设施来谈论......!! !!!!!!!!!
【解决方案3】:

首先,JavaScriptSerializer.Serialize 不会返回您发布的字符串,它会返回正确引用的字符串:

class Item
{
    public string name { get; set; }
    public string place { get; set; }
}
....
var t = new Item {name = "abc", place = "xyz"};
var s = JsonConvert.SerializeObject(t);
Debug.Assert(s == "{\"name\":\"abc\",\"place\":\"xyz\"}");

这确实是一个关于 CMD 以及它如何使用引号的问题。

问题在于命令行使用" 作为分隔符,因此您必须对字符串中的引号进行转义,就像使用.NET 一样。

幸运的是,反斜杠也是 CMD 中的转义字符,因此myprog.exe "{\"name\":\"abc\",\"place\":\"xyz\"}" 将保留引号,以下将起作用

var newItem = new JavaScriptSerializer().Deserialize<Item>(args[0]);

转义引号的一种快速而肮脏的方法是将它们替换为\"

var encoded=s.Replace("\"", "\\\"");

注意多个反斜杠 - 反斜杠和引号都需要转义。

更新

可以通过使用管道或将 json 字符串保存到单独的文件来避免完全转义混淆 json 字符串。在这两种情况下,重要的是人类能够编辑脚本而无需对命令和数据进行编码/解码。例如。管理员应该能够快速更正或检查参数,而无需对简单的 json 字符串进行编码/解码。

在使用脚本时,在命令行中使用 json 字符串是有意义的,在两种情况下:

  1. 第一个程序创建一个必须由第二个程序处理的 Json 输出
  2. 第一个程序生成一个批处理文件,调用第二个程序,传递一个 json 参数。

在第一种情况下,如果第一个程序简单地写入控制台,而第二个程序从控制台读取,而不是检查其参数,则第一个程序的输出可以通过管道传输到第二个程序的输入。在这种情况下不需要转义,因为字符串按原样从第一个程序传递到第二个程序。

这有一个额外的好处,即可以将 json 字符串写入中间文件,例如。以供检查或允许稍后运行第二个程序。

在第二种情况下,第一个程序创建文件并使用管道将其传递给第二个程序,或者将文件的路径作为参数传递。

第二个程序允许管道所需的唯一更改是使用Console.ReadToEnd() 从控制台读取而不是args 数组。

例如,第一个程序应该以:

var s = JsonConvert.SerializeObject(t);
Console.WriteLine(s);

第二个程序应该从控制台读取输入:

var json=Console.ReadToEnd();
var newItem= new JavaScriptSerializer().Deserialize<Item>(t);

这将允许您创建一个简单的脚本:

first.exe | second.exe

或者

myJson.json > second.exe

【讨论】:

  • 查看我接受的答案。第一段说“我猜双引号被删除了,因为它们在 CLI 世界中有意义。”,也就是说,归根结底,就像你在回答中所说的那样“问题是命令行使用“作为分隔符 [...]”。您的回答为提供替代解决方案提供了价值...
  • 在 .NET CLI 中是公共语言基础结构
猜你喜欢
  • 2020-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-08
  • 1970-01-01
  • 2011-12-05
  • 1970-01-01
相关资源
最近更新 更多