Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Powershell与.NET中的Newtonsoft Json Linq存在问题?_Powershell_Json.net - Fatal编程技术网

Powershell与.NET中的Newtonsoft Json Linq存在问题?

Powershell与.NET中的Newtonsoft Json Linq存在问题?,powershell,json.net,Powershell,Json.net,我在C#.NET应用程序中有以下代码 JObject myJObject = new JObject(); JArray myJArray = new JArray(); myJObject.Add( (new JProperty("PropA", (new JObject(new JProperty("PropA1", ""))))) ); Console.WriteLine(myJObject.ToString());

我在C#.NET应用程序中有以下代码

 JObject myJObject = new JObject();
 JArray myJArray = new JArray();

 myJObject.Add(
                (new JProperty("PropA", (new JObject(new JProperty("PropA1", "")))))
              );

 Console.WriteLine(myJObject.ToString());
它按预期工作,我得到的输出是

{ “PropA”:{ “1”:” } }

然而,当我在powershell中执行完全相同的代码时(但已翻译)

它爆炸了,我得到了错误

新对象:异常调用带有“1”参数的“.ctor”:“无法将Newtonsoft.Json.Linq.JValue添加到Newtonsoft.Json.Linq.JObject。”

有趣的是,如果我使用相同的代码,但添加了两个属性,它就可以工作了

  $myJObject.Add(
                 (New-Object JProperty("PropA",(New-Object JObject((New-Object JProperty("PropA1","")), (New-Object JProperty("PropA2",""))))))
                 ) 
但我当然明白了

{ “PropA”:{ “1”:“1”, “2”:” } }


我做错了什么?

我怀疑出于某种原因,PowerShell没有解析正确的
JObject
构造函数,尽管我不知道为什么。我用你的例子玩了一段时间,无法说服PowerShell做正确的事情

我建议重写脚本,以便使用空构造函数创建
JObjects
,然后使用
Add
方法向它们添加属性。我能够通过以下方式获得您想要的输出:

$emptyVal = New-Object JValue ""
$innerObject = New-Object JObject
$innerObject.Add("PropA1", $emptyVal)
$myJObject = New-Object JObject
$myJObject.Add("PropA", $innerObject)

Write-Host $myJObject.ToString()
tl;dr

using namespace Newtonsoft.Json.Linq
Add-Type -Path "C:\Temp\Newtonsoft.Json.dll" 

[JObject] $myJObject = New-Object JObject

$myJObject.Add(
  (New-Object JProperty "PropA",
                        (New-Object JObject (
                            # Note the , (...) around this New-Object call,
                            # which wraps the resulting JProperty instance in a 
                            # single-element array.    
                            , (New-Object JProperty "PropA1", "")
                          )
                        )
  )
)

$myJObject.ToString() 
替代方法,使用调用构造函数的类型上可用的PSv5+static
:new()
方法

[JObject] $myJObject = New-Object JObject

$myJObject.Add(
  [JProperty]::new("PropA",
    [JObject]::new(
      # No workaround needed.
      [JProperty]::new("PropA1", "")
    )
  )
)

$myJObject.ToString() 
New-Object JObject (, (New-Object JProperty "PropA1", "")) # OK - wrapped in array

在正确的轨道上:问题是内部
JObject
构造函数在使用
New Object
cmdlet调用时没有接收作为参数传递的
JProperty
实例

# *Seemingly* the equivalent of: new JObject(new JProperty("PropA1", ""))
New-Object JObject (New-Object JProperty "PropA1", "") # !! FAILS
注意使用类似shell的语法-空格分隔的参数,参数列表周围没有括号-因为这是像
New Object
这样的cmdlet所期望的-这些不是方法调用;它们是在中解析的PowerShell命令

JProperty
实例包装到助手数组中,解决了该问题

[JObject] $myJObject = New-Object JObject

$myJObject.Add(
  [JProperty]::new("PropA",
    [JObject]::new(
      # No workaround needed.
      [JProperty]::new("PropA1", "")
    )
  )
)

$myJObject.ToString() 
New-Object JObject (, (New-Object JProperty "PropA1", "")) # OK - wrapped in array
是PowerShell的数组构造操作符,因此,
创建单个元素
对象[]
数组,包装
的结果[1]

但是,通过使用PSv5+静态
::new()
构造方法可以避免问题<代码>::new()可用于所有类型,并允许您使用方法语法调用构造函数:


关于标量
JProperty
参数不能与PowerShell中的
新对象一起工作的原因

[JObject] $myJObject = New-Object JObject

$myJObject.Add(
  [JProperty]::new("PropA",
    [JObject]::new(
      # No workaround needed.
      [JProperty]::new("PropA1", "")
    )
  )
)

$myJObject.ToString() 
New-Object JObject (, (New-Object JProperty "PropA1", "")) # OK - wrapped in array
由于
JProperty
类型实现了
IEnumerable
接口,因此PowerShell在绑定到(隐含的)
-ArgumentList
参数(本身就是
对象[]
-typed)时,会尝试枚举单个
JProperty
实例,而不是将其作为自身传递。
这会失败,因为
JObject
构造函数随后会看到该枚举的结果,即表示JSON属性值的
JValue
实例,并且不允许从
JValue
实例构造
JObject
实例,如错误消息所示-请参阅

将这样一个实例包装到数组中可以绕过这个问题:它可以防止
JProperty
实例的枚举,并安全地将其传递到辅助
对象[]
实例中

如果要传递给
新对象JObject
的是一个数组,例如传递两个
JProperty
实例的示例,那么问题也可以避免

还要注意,强制转换到
[JObject]
也可以,但只能使用一个属性:

New-Object JObject ([JObject] (New-Object JProperty "PropA1", "")) # OK with 1 prop.

并非说Powershell具有内置的JSON支持,它允许方便地将哈希表和自定义对象转换为JSON并返回:

# Convert a nested hashtable to JSON
PS> @{ PropA = @{ PropA1 = 42 } } | ConvertTo-Json -Compress
{"PropA":{"PropA1":42}}

# Convert JSON to a custom object [pscustomobject] with property
# .PropA whose value is another custom object, with property .PropA1
PS> '{"PropA":{"PropA1":42}}' | ConvertFrom-Json

PropA
-----
@{PropA1=42}
因此,除非您有特殊要求和/或性能问题,否则PowerShell的内置功能可能就足够了,您甚至可以通过JSON字符串表示将自定义对象/哈希表转换为
JObject
/
JToken
实例,尽管成本不低:

PS> [JToken]::Parse((@{ PropA = @{ PropA1 = 42 } } | ConvertTo-Json -Compress)).ToString()
{
  "PropA": {
    "PropA1": 42
  }
}

[1] 请注意,
@(…)
,数组子表达式操作符在这种情况下不能正常工作,因为它在将结果包装到
[object[]
数组之前也涉及到
JProperty
实例的不必要枚举:

# !! FAILS too: 
# The JProperty instance is again enumerated, resulting in a single
# JValue instance, which is what @(...) then wraps in a
# single-element [object[]] array.
$var = New-Object JProperty "PropA1", ""
New-Object JObject @($var)
奇怪的是,如果您直接将
新对象
调用放在其中,您就可以逃脱
@(…)


在这种情况下,
@(…)
阻止枚举是因为命令输出(例如,
@(新对象…
)-与表达式输出(例如,
@($var)
)相反,
@(…)
)没有枚举;也就是说,如果命令输出可枚举的内容/作为一个整体的集合-这是
新对象在实例化此类类型时所做的操作-
@(…)
将其包装为单个元素
[Object[]
数组。(顺便说一句:
$(…)
将导致枚举)。

谢谢您的尝试。我很高兴你看到了和我一样的事情,因为有时候我觉得我疯了!我发现的另一个解决方法是添加这两个属性,以便获得正确的重载,然后返回并删除第二个属性,这样最终结果就是我想要的。