Powershell : JSON as commandline args

I encountered a problem when I tried to run a script and pass a JSON string as an argument on Powershell like

 PS > $PSVersionTable
 Name                           Value
 ----                           -----
 PSVersion                      5.1.19041.1320
 PSEdition                      Desktop
 PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
 BuildVersion                   10.0.19041.1320
 CLRVersion                     4.0.30319.42000
 WSManStackVersion              3.0
 PSRemotingProtocolVersion      2.3
 SerializationVersion           1.1.0.1

PS > cat .\foo.py
import sys
print(sys.argv)  # I used argparse acutually
PS > python .\foo.py $JsonString

Problem

The problem is the JSON string was parsed and split incorrectly.

PS > $JsonString = '{"foo":"This is the value"}'
PS > python .\foo.py -json $JsonString
# quotes are erased!
['.\\foo.py', '-json', '{foo:This is the value}']

The double quotes are erased by powershell. So next escaped the quotes.

PS > $JsonString = '{\"foo\":\"This is the value\"}'
PS > python .\foo.py -json $JsonString
# split incorrectly!
['.\\foo.py', '-json', '{"foo":"This', 'is', 'the', 'value"}']

Then the quotes remain, however the value is split by the blank space! I read powershell doc and found the way I escaped quotes was wrong. I have to duplicate quotes rather than adding “\”.

$JsonString = '{""foo"":""This is the value""}'
PS > python .\foo.py -json $JsonString
# it's fine
['.\\foo.py', '-json', '{"foo":"This is the value"}'] 

That works fine, but I found another problem. If the JSON string doesn’t contain any blank spaces, it doesn’t work.

# If the JSON doesn't contain blank
PS > $JsonString = '{""foo"":""Thisisthevalue""}'
PS > python .\foo.py -json $JsonString
# quotes are erased again!
['.\\foo.py', '-json', '{foo:Thisisthevalue}']

Solution

According to the powershell doc, there are two steps when the arguments are passed from powershell to the process.

  1. Powershell erases the quotes
  2. Powershell splits the arguments by blank space

Hence, I have to pass JSON string arguments as follows.

# 1. escape double quotes within JSON by duplicating so that powershell doen't erase them
PS > $JsonString = '{"foo":"This is the value"}'.Replace('"','""')
# 2. surround the JSON string by " `" " so that powershell doen't split that
PS > python .\foo.py -json `"$JsonString`"  
['.\\foo.py', '-json', '{"foo":"This is the value"}']  
# it works wheather it contains blank space or not
# although I still can't understand why the quotes are erased without adding `"
PS > $JsonString = '{"foo":"Thisisthevalue"}'.Replace('"','""')
PS > python .\foo.py -json `"$JsonString`"
['.\\foo.py', '-json', '{"foo":"Thisisthevalue"}']
# if it contains double quotes as value, use " \\"" "
PS > $JsonString = '{"foo":"This is the \\"value\\"."}'.Replace('"','""')
PS > python .\foo.py -json `"$JsonString`"
['.\\foo.py', '-json', '{"foo":"This is the \\"value\\"."}']

Leave a Reply

Your email address will not be published. Required fields are marked *