我想使用PowerShell设置嵌套对象属性的值。当您尝试设置第一级属性的值时,它很简单:
$propertyName = "someProperty"
$obj.$propertyName = "someValue" # ← It works
对于嵌套属性,它不起作用:
$propertyName = "someProperty.someNestedProperty"
$obj.$propertyName = "someValue" # ← It doesn't work and raises an error.
如何使用PowerShell按属性名设置嵌套对象属性的值?
MCVE
对于那些想要重现问题的人,这是一个简单的例子:
$Obj= ConvertFrom-Json '{ "A": "x", "B": {"C": "y"} }'
# Or simply create the object:
# $Obj= @{ A = "x"; B = @{C = "y"} }
$Key = "B.C"
$Value = "Some Value"
$Obj.$Key = $Value
运行该命令,您将收到错误:
"该物业' B.C'在这个对象上找不到。验证 属性存在且可以设置。"
答案 0 :(得分:4)
我创建了SetValue
和GetValue
方法,让您通过名称动态获取和设置对象(包括json对象)的嵌套属性,并且它们完美无缺!
它们是递归方法,它们通过拆分嵌套属性名称来逐步解析复杂属性并获取嵌套属性。
按名称划分的嵌套属性的GetValue和SetValue
# Methods
function GetValue($object, $key)
{
$p1,$p2 = $key.Split(".")
if($p2) { return GetValue -object $object.$p1 -key $p2 }
else { return $object.$p1 }
}
function SetValue($object, $key, $Value)
{
$p1,$p2 = $key.Split(".")
if($p2) { SetValue -object $object.$p1 -key $p2 -Value $Value }
else { $object.$p1 = $Value }
}
示例强>
在以下示例中,我使用B.C
动态设置SetValue
并使用GetValue
方法按名称获取其值:
# Example
$Obj = ConvertFrom-Json '{ "A": "x", "B": {"C": "y"} }'
# Or simply create the object:
# $Obj = @{ A = "x"; B = @{C = "y"} }
$Key = "B.C"
$Value = "Changed Dynamically!"
SetValue -object $Obj -key $Key -Value $Value
GetValue -object $Obj -key $Key
答案 1 :(得分:1)
我可以提出对Reza解决方案的升级。使用此解决方案,您可以具有许多级别的嵌套属性。
function GetValue($object, [string[]]$keys)
{
$propertyName = $keys[0]
if($keys.count.Equals(1)){
return $object.$propertyName
}
else {
return GetValue -object $object.$propertyName -key ($keys | Select-Object -Skip 1)
}
}
function SetValue($object, [string[]]$keys, $value)
{
$propertyName = $keys[0]
if($keys.count.Equals(1)) {
$object.$propertyName = $value
}
else {
SetValue -object $object.$propertyName -key ($keys | Select-Object -Skip 1) -value $value
}
}
用法
$Obj = ConvertFrom-Json '{ "A": "x", "B": {"C": {"D" : "y"}} }'
SetValue $Obj -key "B.C.D".Split(".") -value "z"
GetValue $Obj -key "B.C.D".Split(".")
答案 2 :(得分:1)
您的own solutions 是有效的,但不支持将索引访问作为嵌套属性访问路径的一部分(例如,
from itertools import permutations
while True:
numnum = input('Please choose number of cards (enter anything other than 4 and 5 to quit the program):')
if numnum == '4':
try:
a = int(input("Please enter the first number:"))
b = int(input("Please enter the second number:"))
c = int(input("Please enter the third number:"))
d = int(input("Please enter the fourth number:"))
except:
print('WARNING: Please enter a real number!')
continue
print('Processing...')
my_list = [a, b, c, d]
# Randomly arrange a list of 4 integers
result = [c for c in permutations(my_list, 4)]
symbols = ["+", "-", "*", "/"]
list2 = [] # Calculate the list of 24 permutations and combinations
flag = False
for one, two, three, four in result:
for s1 in symbols:
for s2 in symbols:
for s3 in symbols:
if s1 + s2 + s3 in ['+++', '***', '+--', '++-', '**/', '*//', '///']:
express = ["{0}{1}{2}{3}{4}{5}{6}".format(one, s1, two, s2, three, s3, four)]
elif s1 + s2 + s3 in ['+-+', '-++', '-+-', '--+', '*/*', '/**', '/*/', '//*']:
continue
else:
express = ["({0}{1}{2}){3}{4}{5}{6}".format(one, s1, two, s2, three, s3, four),
"({0}{1}{2}{3}{4}){5}{6}".format(one, s1, two, s2, three, s3, four),
"{0}{1}({2}{3}{4}){5}{6}".format(one, s1, two, s2, three, s3, four),
"{0}{1}({2}{3}{4}{5}{6})".format(one, s1, two, s2, three, s3, four),
"{0}{1}{2}{3}({4}{5}{6})".format(one, s1, two, s2, three, s3, four),
"(({0}{1}{2}){3}{4}){5}{6}".format(one, s1, two, s2, three, s3, four),
"({0}{1}{2}){3}({4}{5}{6})".format(one, s1, two, s2, three, s3, four),
"({0}{1}({2}{3}{4})){5}{6}".format(one, s1, two, s2, three, s3, four),
"{0}{1}(({2}{3}{4}){5}{6})".format(one, s1, two, s2, three, s3, four),
"{0}{1}({2}{3}({4}{5}{6}))".format(one, s1, two, s2, three, s3, four)]
for e in express:
try:
if eval(e) == 24:
list2.append(e)
flag = True
except ZeroDivisionError:
pass
for c in list2:
if '+(' in c or '-(' in c or ')-' in c or ')+' in c or ')*' in c:
continue
print(c)
if not flag:
print("NO solution...")
elif numnum == '5':
try:
a = int(input("Please enter the first number:"))
b = int(input("Please enter the second number:"))
c = int(input("Please enter the third number:"))
d = int(input("Please enter the fourth number:"))
e = int(input('Please enter the fifth number:'))
except:
print('WARNING: Please enter a real number!')
continue
print('Processing...')
my_list = [a, b, c, d, e]
# Randomly arrange a list of 4 integers
result = [c for c in permutations(my_list, 5)]
symbols = ["+", "-", "*", "/"]
list2 = [] # Calculate the list of 24 permutations and combinations
flag = False
for one, two, three, four, five in result:
for s1 in symbols:
for s2 in symbols:
for s3 in symbols:
for s4 in symbols:
if s1 + s2 + s3 + s4 in ['++++', '****', '+---', '+++-', '++--', '**//', '*///', '///',
'***/']:
express = ["{0}{1}{2}{3}{4}{5}{6}{7}{8}".format(one, s1, two, s2, three, s3, four, s4, five)]
elif (s1, s2, s3, s4) in permutations(['*', '/', '/', '/']) \
or (s1, s2, s3, s4) in permutations(['*', '*', '/', '/']) \
or (s1, s2, s3, s4) in permutations(['*', '*', '*', '/']) \
or (s1, s2, s3, s4) in permutations(['+', '-', '-', '-']) \
or (s1, s2, s3, s4) in permutations(['+', '+', '-', '-']) \
or (s1, s2, s3, s4) in permutations(['+', '+', '+', '-']):
continue
else:
express = ["({0}{1}{2}){3}{4}{5}{6}{7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"({0}{1}{2}{3}{4}){5}{6}{7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"({0}{1}{2}{3}{4}{5}{6}){7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}({2}{3}{4}){5}{6}{7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}({2}{3}{4}{5}{6}){7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}({2}{3}{4}{5}{6}{7}{8})".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}{2}{3}({4}{5}{6}){7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}{2}{3}({4}{5}{6}{7}{8})".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}{2}{3}{4}{5}({6}{7}{8})".format(one, s1, two, s2, three, s3, four, s4, five),
"(({0}{1}{2}){3}{4}){5}{6}{7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"(({0}{1}{2}){3}{4}{5}{6}){7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"({0}{1}{2}){3}({4}{5}{6}){7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"({0}{1}{2}){3}({4}{5}{6}{7}{8})".format(one, s1, two, s2, three, s3, four, s4, five),
"({0}{1}{2}){3}{4}{5}({6}{7}{8})".format(one, s1, two, s2, three, s3, four, s4, five),
"({0}{1}{2}{3}{4}){5}({6}{7}{8})".format(one, s1, two, s2, three, s3, four, s4, five),
"(({0}{1}{2}{3}{4}){5}{6}){7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"({0}{1}({2}{3}{4})){5}{6}{7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"({0}{1}({2}{3}{4}){5}{6}){7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"({0}{1}{2}{3}({4}{5}{6})){7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"({0}{1}({2}{3}{4}{5}{6})){7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}(({2}{3}{4}){5}{6}){7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}(({2}{3}{4}){5}{6}{7}{8})".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}({2}{3}{4}){5}({6}{7}{8})".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}({2}{3}({4}{5}{6})){7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}(({2}{3}{4}{5}{6}){7}{8})".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}({2}{3}({4}{5}{6}){7}{8})".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}({2}{3}({4}{5}{6}{7}{8}))".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}({2}{3}{4}{5}({6}{7}{8}))".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}{2}{3}(({4}{5}{6}){7}{8})".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}{2}{3}({4}{5}({6}{7}{8}))".format(one, s1, two, s2, three, s3, four, s4, five),
"((({0}{1}{2}){3}{4}){5}{6}){7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"(({0}{1}{2}){3}({4}{5}{6})){7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"({0}{1}{2}){3}(({4}{5}{6}){7}{8})".format(one, s1, two, s2, three, s3, four, s4, five),
"({0}{1}{2}){3}({4}{5}({6}{7}{8}))".format(one, s1, two, s2, three, s3, four, s4, five),
"(({0}{1}({2}{3}{4})){5}{6}){7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"({0}{1}({2}{3}{4})){5}({6}{7}{8})".format(one, s1, two, s2, three, s3, four, s4, five),
"({0}{1}(({2}{3}{4}){5}{6})){7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"({0}{1}({2}{3}({4}{5}{6}))){7}{8}".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}((({2}{3}{4}){5}{6}){7}{8})".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}(({2}{3}{4}){5}({6}{7}{8}))".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}(({2}{3}({4}{5}{6})){7}{8})".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}({2}{3}(({4}{5}{6}){7}{8}))".format(one, s1, two, s2, three, s3, four, s4, five),
"{0}{1}({2}{3}({4}{5}({6}{7}{8})))".format(one, s1, two, s2, three, s3, four, s4, five)]
for e in express:
try:
if eval(e) == 24:
list2.append(e)
flag = True
except ZeroDivisionError:
pass
for c in list2:
if '+(' in c or '-(' in c or ')-' in c or ')+' in c or ')*' in c:
continue
print(c)
if not flag:
print("NO solution...")
else:
break
)
一个简单的替代方法是使用B[1].C
(Invoke-Expression
)。
虽然它should generally be avoided,但在特殊情况下它提供了最简单的解决方案,这就是其中之一:
假设您完全控制或隐式信任属性访问字符串:
iex
如果您不信任输入,您可以避免不必要的命令注入,如下所示:
$obj = ConvertFrom-Json '{ "A": "x", "B": [ {"C": "y"}, { "C": "z"} ] }'
$propPath = 'B[1].C'
# GET
Invoke-Expression "`$obj.$propPath" # -> 'z'
# SET
$value = 'Some Value'
Invoke-Expression "`$obj.$propPath = `$value"
有关安全打包上述功能的便利功能/ETS 方法,请参阅this answer。