Powershell无需迭代即可直接引用JSON对象

时间:2018-10-22 07:47:17

标签: json powershell

这里是学习powershell的新功能,只要其自身包含在给定脚本中,它就可以真正打开任何解决方案

很难在文档中找到与此相关的任何内容,这也许意味着什么都没有?

PSVersion 5.1

内部版本:10.0.17134

不知道特定的JSON标准或文件设置,但是我们可以使用它作为示例:

{
  "foo" : ["foo1", "foo2", "foo3"],
  "bar" : {
     "bar-foo" : 20,
     "bar-bar" : {
       "bar-bar-foo : "here"
     }
   }
}

我想直接导航到JSON KVP,因为我会事先知道该属性,并且它是完整的嵌套路径。

例如,输入参数为:

.\ScriptName -JsonProp ["bar"]["bar-bar"]["bar-bar-foo"]

我的脚本当前正在使用ConvertTo-Json,其源代码是任何给定的.json文件,但是如果有一种更简便或更友好的方式来显式导航json对象,我将不知所措。

目标是更改该属性的值并将其写出到文件中

$json = Get-Content -Raw -Path $path | ConvertFrom-Json

$json.$JsonProp = "there"

据我所知,Json对象必须使用点表示法,但是我已经尝试过使用没有解析度的字符串,例如,将参数拆分:

.\ScriptName -JsonProp bar.bar-bar.bar-bar-foo

$json.$JsonProp = "there"

如果您对Powershell的文献有任何建议,那么我是这个话题,请告诉我。

3 个答案:

答案 0 :(得分:2)

您的JSON对象中标识的任何包含非字母字符的内容都必须加引号:

$rawJson = @"
{
  "foo": ["foo1", "foo2", "foo3"],
  "bar": {
     "bar-foo": 20,
     "bar-bar": {
       "bar-bar-foo" : "here"
     }
  }
}
"@

$json = ConvertFrom-Json -InputObject $rawJson

# Note the quotes!!
$json.bar."bar-bar"."bar-bar-foo" = "Hello thar!"

$json | ConvertTo-Json

结果

{
    "foo":  [
                "foo1",
                "foo2",
                "foo3"
            ],
    "bar":  {
                "bar-foo":  20,
                "bar-bar":  {
                                "bar-bar-foo":  "Hello thar!"
                            }
            }
}

使用“ Dymanic” JSON路径

重要免责声明: 此代码很危险。您可以将所有排序传递给$jsonPath变量,它将被执行。这类似于SQL注入,您需要非常小心。

Obligatory xkcd

$rawJson = @"
{
  "foo": ["foo1", "foo2", "foo3"],
  "bar": {
     "bar-foo": 20,
     "bar-bar": {
       "bar-bar-foo" : "here"
     }
  }
}
"@

$jsonPath = 'bar."bar-bar"."bar-bar-foo"'
$newValue = "Hello thar!"
$command = "`$json.$jsonPath = '$newValue'"

$json = ConvertFrom-Json -InputObject $rawJson

Invoke-Expression $command

$json | ConvertTo-Json

答案 1 :(得分:1)

如果有一种更简便或更友好的方式来明确导航我所知的json对象

是的,有很多...这是一个使用jq JSON command line parser

的示例

提供了JSON示例,要将值here更改为there,只需执行以下操作:

jq '.bar."bar-bar"."bar-bar-foo" |= "there"' file
{
  "foo": [
    "foo1",
    "foo2",
    "foo3"
  ],
  "bar": {
    "bar-foo": 20,
    "bar-bar": {
      "bar-bar-foo": "there"
    }
  }
}

jq中,赋值运算符为|=

双引号JSON密钥并不总是强制性的,但这是为了避免与减法运算符混淆。

答案 2 :(得分:1)

这是一种方法:

$newValue = "there"
Invoke-Expression ('$json.' + $JsonProp + ' = $newValue')

您必须在参数中包括引号:

.\ScriptName -JsonProp "bar.'bar-bar'.'bar-bar-foo'"

为防止输入错误或安全问题,您可以/应该事先验证参数,例如使用简单的正则表达式检查:

# (Note: This is just a quick example. Not pretty or complete, but does the job.)
if ($JsonProp -notmatch '^([a-zA-Z0-9_\-]+|''[a-zA-Z0-9_\-"]+''|"[a-zA-Z0-9_\-'']+")(\.([a-zA-Z0-9_\-]+|''[a-zA-Z0-9_\-"]+''|"[a-zA-Z0-9_\-'']+"))*$') {
    throw "Invalid json property."
}