Reputation: 521
I am trying to create a web API that will convert the output of a PowerShell command to JSON. Is there a library that can do this or convert a PSObject to JSON?
The PSObject properties changes depending on the command that generates it. I tried passing the PSObject to "ConvertTo-Json", but I got extra object information.
PowerShell command:
Get-Process | Select -Property Handles,ProcessName | ConvertTo-Json
The output after 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 command to BeginInvoke.
PowerShell command:
Get-Process | Select -Property Handles,ProcessName
The output after 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>\"}}]
Upvotes: 4
Views: 6697
Reputation: 29
For anyone still looking for a solution to this, the built in JSON converter (ConvertTo-Json) from Powershell can be utilised as such:
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);
}
}
}
Upvotes: 2
Reputation: 1868
This works for me. Try it out.
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;
Upvotes: 0
Reputation: 547
If you're OK with using a third-party library, then JSON.NET has the JsonConvert
class. It's fairly straightforward to use: JsonConvert.SerializeObject(myObj)
will return a string containing the JSON.
I find this to be a bit easier than trying to programmatically call PowerShell from C# code.
If there are extra properties that you would like to omit, then JsonConvert allows you to implement an IContractResolver to specify which properties you would like.
It ends up looking like so:
JsonConvert.SerializeObject(myObj, new JsonSerializerSettings { ContractResolver = new MyContractResolver() });
And the ContractResolver looks like so:
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;
}
}
Of course, you can make the condition for the properties anything you like.
Upvotes: 2