I'm serialize an object to json string and passing that to an app through command line but when I receive the arguments in the app, this is no longer a json string but a regular string .
I'm using below code to create json string
var jsonStr = new JavaScriptSerializer().Serialize(obj);
string that I'm passing - "{"name":"abc","place":"xyz"}"
string that I receive - "{name:abc,place:xyz}";
How can I maintain the structure of the json string ?
I guess double quots are wiped out because they've meaning inside the CLI world.
I would say that converting the whole JSON into a base 64 string, and then, in the CLI internally turn into regular string again should work:
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...
Answering to some comment from @Panagiotis Kanavos...
The CLI doesn't corrupt any string - people would have noticed by now.
If the OP sends a different string, the problem is in that code, not
the CLI
As I pointed out in comments as answers to your ones, I know that inside .NET world we don't need to escape a JSON and maybe in other environments there's also no need to do this.
I suggested base 64 approach because it's a bullet-proof solution, and as OP provided few details and insufficient code samples, at the end of the day, I believe it's the base 64 approach is as valid as just escaping double quots, but it also provides an added value: it escapes any special character in addition to "
.
BTW, there're actual cases where a CLI prevents some characters. redis-cli
on Windows doesn't allow curly brackets...
Update 2
Since @Panagiotis Kanavos has confused CLI with Common Language Interface, I want to be sure that everyone that reads my answer understand CLI as Command Line Interface.
Just escape quotes with backslashes so CMD will not remove quotes inside a JSON.
String which should be passed:
"{\"name\":\"abc\",\"place\":\"xyz\"}"
String which will be received:
{"name":"abc","place":"xyz"}
Use this code to escape the string:
string jsonString = new JavaScriptSerializer().Serialize(obj);
string escapedString = jsonString.Replace("\"", "\\\"");
First, JavaScriptSerializer.Serialize doesn't return the string you posted, it returns a properly quoted string:
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\"}");
This is really a question about CMD and how it uses quotes.
The problem is that the command line uses "
as a delimiter so you have to escape quotes in your strings, just as you would do with .NET.
Luckily, the backslash is the escape character in CMD as well, so myprog.exe "{\"name\":\"abc\",\"place\":\"xyz\"}"
will preserve the quotes, and the following will work
var newItem = new JavaScriptSerializer().Deserialize<Item>(args[0]);
A quick and dirty way to escape quotes is to replace them with \"
:
var encoded=s.Replace("\"", "\\\"");
Notice the multiple backslashes - both the backslash and the quote need to be escaped.
UPDATE
It's possible to avoid escaping entirely and obfuscating the json string either by using piping or by saving the json string to a separate file. In both cases, it's important for humans to be able to edit the script without having to encode/decode the commands and data. Eg. an administrator should be able to make quick corrections or inspect the parameters without having to encode/decode a simple json string.
Using a json string in a command line makes sense when using scripts, in two scenarios:
- The first program creates a Json output that must be processed by the second program
- The first program generates a batch file calling the second program, passing a json parameter.
In the first scenario, the first program's output can be piped to the second program's input if the fist program simply writes to the console and the second program reads from the console, instead of inspecting its parameters. No escaping is needed in this case because the string is passed as-is from the first program to the second.
This has the additional advantage that the json string can be written to an intermediate file eg. for inspection or to allow running the second program at a later time.
In the second scenario the first program creates the file and either uses piping to pass it to the second program, or passes the file's path as a parameter.
The only change needed by the second program to allow piping is to use Console.ReadToEnd()
to read from the console instead of the args
array.
For example, the first program should end with:
var s = JsonConvert.SerializeObject(t);
Console.WriteLine(s);
and the second program should read the input from the console:
var json=Console.ReadToEnd();
var newItem= new JavaScriptSerializer().Deserialize<Item>(t);
This will allow you to create a script as simple as:
first.exe | second.exe
Or
myJson.json > second.exe