Packs the jq binaries for easy execution from dotnet applications running on Linux (AMD64 and ARM64), macOS (AMD64 and ARM64) and Windows (AMD64 and i386).
When JsonPath falls short, jq is the obvious next step in flexibility
and power for JSON manipulation.
jq is like sed for JSON data - you can use it to slice and filter and map and transform structured data with the same ease that sed, awk, grep and friends let you play with text.
Learn more about jq at https://jqlang.github.io/jq/.
Simple usage for extracting values:
var name = await JQ.ExecuteAsync(
"""
{
"name": "John",
"age": 30
}
""",
".name");For advanced scenarios, use JqParams to access all jq command-line options and JqResult to inspect exit codes and error output:
var result = await JQ.ExecuteAsync(new JqParams("{name: .name, extra: $myvar}")
{
Json = """
{
"name": "John",
"age": 30
}
""",
Args = new Dictionary<string, string> { { "myvar", "value" } },
CompactOutput = true,
SortKeys = true
});
if (result.ExitCode == 0)
Console.WriteLine(result.StandardOutput);
else
Console.Error.WriteLine(result.StandardError);The JqResult class provides:
ExitCode- the process exit codeStandardOutput- the standard output from jqStandardError- the standard error from jq- Implicit conversion to
string(returnsStandardOutput)
The JqParams class supports:
- Output options:
RawOutput,CompactOutput,MonochromeOutput,ColorOutput,AsciiOutput,SortKeys,JoinOutput,Tab,Indent - Processing options:
Slurp,NullInput,ExitStatus - Variable passing:
Args(--arg),ArgsJson(--argjson),SlurpFiles(--slurpfile),RawFiles(--rawfile)
The JQ.Path static property provides the full path to the jq binary that's appropriate
for the current OS and architecture so you can execute it directly if needed.
The following is a real-world scenario where WhatsApp Cloud API messages are converted into clean polymorphic JSON for nice OO deserialization via System.Text.Json.
Rather than navigating deep into the JSON structure, we can use jq to transform the payload
into what we expect for deserialization of a text message:
{
"id": "wamid.HBgNMTIwM==",
"timestamp": 1678902345,
"to": {
"id": "792401583610927",
"number": "12025550123"
},
"from": {
"name": "Mlx",
"number": "12029874563"
},
"content": {
"$type": "text",
"text": "π"
}
}The original JSON looks like the following:
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "813920475102346",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "12025550123",
"phone_number_id": "792401583610927"
},
"contacts": [
{
"profile": { "name": "Mlx" },
"wa_id": "12029874563"
}
],
"messages": [
{
"from": "12029874563",
"id": "wamid.HBgNMTIwM==",
"timestamp": "1678902345",
"text": { "body": "\ud83d\ude0a" },
"type": "text"
}
]
},
"field": "messages"
}
]
}
]
}The following JQ query turns the latter info the former:
.entry[].changes[].value.metadata as $phone |
.entry[].changes[].value.contacts[] as $user |
.entry[].changes[].value.messages[] |
{
id: .id,
timestamp: .timestamp | tonumber,
to: {
id: $phone.phone_number_id,
number: $phone.display_phone_number
},
from: {
name: $user.profile.name,
number: $user.wa_id
},
content: {
"$type": "text",
text: .text.body
}
}This allows you to focus your C# code into the actual object model you want to work with, rather than the one imposed by the JSON format of external APIs.
See this code in action at Devlooped.WhatsApp.