在c#中将psoobjects(或PS Command)转换为JSON

本文关键字:Command 转换 JSON PS 中将 psoobjects | 更新日期: 2023-09-27 18:08:36

我正在尝试创建一个web API,将PowerShell命令的输出转换为JSON。是否有一个库可以做到这一点或将PSObject转换为JSON?

PSObject属性根据生成它的命令而改变。我尝试将PSObject传递给"ConvertTo-Json",但我得到了额外的对象信息。

PowerShell命令:
Get-Process | Select -Property Handles,ProcessName | ConvertTo-Json

JsonConvert.SerializeObject()后的输出:

"{'"CliXml'":'"<Objs Version='''"1.1.0.1'''" xmlns='''"http://schemas.microsoft.com/powershell/2004/04'''">''r''n  <Obj RefId='''"0'''">''r''n<TN RefId='''"0'''">''r''n <T>System.String</T>''r''n      <T>System.Object</T>''r''n    </TN>''r''n    <ToString>[_x000D__x000A_    {_x000D__x000A_'''"Handles'''":163,_x000D__x000A_'''"ProcessName'''":'''"AppleMobileDeviceService'''"_x000D__x000A_},_x000D__x000A_    {_x000D__x000A_'''"Handles'''":  972,_x000D__x000A_'''"ProcessName'''":'''"CcmExec'''"_x000D__x000A_},_x000D__x000A_{_x000D__x000A_'''"Handles'''":  1838,_x000D__x000A_'''"ProcessName'''":'''"ccSvcHst'''"_x000D__x000A_}"

PowerShell命令给BeginInvoke.

PowerShell命令:
Get-Process | Select -Property Handles,ProcessName

JsonConvert.SerializeObject(PSObj)后的输出:

"[{'"CliXml'":'"<Objs Version='''"1.1.0.1'''" xmlns='''"http://schemas.microsoft.com/powershell/2004/04'''">''r''n  <Obj RefId='''"0'''">''r''n    <TN RefId='''"0'''">''r''n      <T>Selected.System.Diagnostics.Process</T>''r''n      <T>System.Management.Automation.PSCustomObject</T>''r''n      <T>System.Object</T>''r''n    </TN>''r''n    <ToString>@{Handles=163; ProcessName=AppleMobileDeviceService}</ToString>''r''n    <Obj RefId='''"1'''">''r''n      <TNRef RefId='''"0'''" />''r''n      <MS>''r''n        <I32 N='''"Handles'''">163</I32>''r''n        <S N='''"ProcessName'''">AppleMobileDeviceService</S></Objs>'"}}]

在c#中将psoobjects(或PS Command)转换为JSON

如果您可以使用第三方库,那么使用JSON。NET有JsonConvert类。使用起来相当简单:JsonConvert.SerializeObject(myObj)将返回一个包含JSON的字符串。

我发现这比试图从c#代码中以编程方式调用PowerShell要容易一些。

如果有你想忽略的额外属性,那么JsonConvert允许你实现一个IContractResolver来指定你想要的属性。

它最终看起来像这样:

JsonConvert.SerializeObject(myObj, new JsonSerializerSettings { ContractResolver = new MyContractResolver() });

ContractResolver看起来是这样的:

public class MyContractResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
        properties = properties.Where(p => p.PropertyName != "OmittedProperty").ToList();
        return properties;
    }
}

当然,您可以为属性设置任何您喜欢的条件

对于仍然在寻找解决方案的人来说,Powershell内置的JSON转换器(ConvertTo-Json)可以这样使用:

using System;
using System.Management.Automation;
using Microsoft.PowerShell.Commands;
using System.Collections.ObjectModel;
namespace PowerJson
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create the Powershell instance, and adds command to be executed
            PowerShell ps = PowerShell.Create();
            ps.AddCommand("Get-Process");
            Collection<PSObject> _ps_results = ps.Invoke();
            // Create a JSON Context Object
            JsonObject.ConvertToJsonContext _json_context = new JsonObject.ConvertToJsonContext(maxDepth: 12, enumsAsStrings: false, compressOutput: false);
            // Converts the PSObject into JSON
            string json_result = JsonObject.ConvertToJson(_ps_results, _json_context);
            // Outputs the result to console
            Console.WriteLine(json_result);
        }
    }
}

这对我有用。试一试。

if (item.TypeNames.FirstOrDefault() == "System.String")
{
    return item.BaseObject.ToString();
}
else
{
    var settings = new Newtonsoft.Json.JsonSerializerSettings
        { ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
    var dict = new Dictionary<string, object>();
    var objMembers = typeof(object).GetMembers();
    var ignoreMembers = new List<string>();
    ignoreMembers.AddRange(
        item.Members.Where(
            i => i.TypeNameOfValue.StartsWith("Deserialized.")).Select(i => i.Name).ToList());
    ignoreMembers.AddRange(objMembers.Select(i => i.Name));
    var filteredMembers =
        item.Members.Where(
            i => ignoreMembers.All(
                ig => ig.ToLower() != i.Name.ToLower())).ToList();
    foreach (var mem in filteredMembers)
    {
        if (!dict.ContainsKey(mem.Name))
        {
            dict.Add(mem.Name, "");
        }
        dict[mem.Name] = mem.Value;
    }
    try
    {
        return Newtonsoft.Json.JsonConvert.SerializeObject(dict, settings);
    }
    catch (Exception e)
    {
    }
}
return null;