Skip to content

Commit 131ce5f

Browse files
committed
Add pattern matching examples for JS Utils
1 parent cf0ca70 commit 131ce5f

File tree

1 file changed

+159
-0
lines changed

1 file changed

+159
-0
lines changed

MyApp/_pages/js-utils.md

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,165 @@ JSON.parse("[{a:1}]") //= new List<object> { new Dictionary<string, object> { {
2727

2828
It can be used to parse dynamic JSON and any primitive JavaScript data type. The inverse API of `JSON.stringify()` is also available.
2929

30+
## Use C# Pattern Matching
31+
32+
### Getting the client_id in a ComfyUI Output
33+
34+
```csharp
35+
var comfyOutput = JSON.parse(json);
36+
var promptId = comfyOutput.Keys.First();
37+
var prompt = (Dictionary<string, object?>)comfyOutput[promptId]!;
38+
if (prompt.TryGetValue("prompt", out var oPromptTuple) && oPromptTuple is List<object> promptTuple)
39+
{
40+
if (promptTuple.Count > 3)
41+
{
42+
var extraData = promptTuple[3];
43+
if (extraData is Dictionary<string, object?> extraDataDict)
44+
{
45+
if (extraDataDict.TryGetValue("client_id", out var oClientId))
46+
{
47+
return oClientId as string;
48+
}
49+
}
50+
}
51+
}
52+
return null;
53+
```
54+
55+
Equivalent implementation using System.Text.Json:
56+
57+
```csharp
58+
using System.Text.Json;
59+
60+
var jsonDocument = JsonDocument.Parse(json);
61+
var root = jsonDocument.RootElement;
62+
63+
var promptId = root.EnumerateObject().FirstOrDefault().Name;
64+
if (!string.IsNullOrEmpty(promptId) && root.TryGetProperty(promptId, out var promptElement))
65+
{
66+
if (promptElement.TryGetProperty("prompt", out var promptTupleElement)
67+
&& promptTupleElement.ValueKind == JsonValueKind.Array)
68+
{
69+
var promptArray = promptTupleElement.EnumerateArray().ToArray();
70+
if (promptArray.Length > 3)
71+
{
72+
var extraDataElement = promptArray[3];
73+
if (extraDataElement.ValueKind == JsonValueKind.Object
74+
&& extraDataElement.TryGetProperty("client_id", out var clientIdElement)
75+
&& clientIdElement.ValueKind == JsonValueKind.String)
76+
{
77+
return clientIdElement.GetString();
78+
}
79+
}
80+
}
81+
}
82+
return null;
83+
```
84+
85+
### Parsing a Gemini API Request
86+
87+
As JSON Object just stored any JSON into untyped generic collections you can use C# pattern matching to navigate and mutate the JSON Object as done in this example which modifies an Gemini API Request to replace the `inline_data.data` string with its length to make it suitable for logging:
88+
89+
```csharp
90+
var obj = (Dictionary<string,object>) JSON.parse(json);
91+
if (obj.TryGetValue("contents", out var oContents)
92+
&& oContents is List<object> contents)
93+
{
94+
foreach (var oContent in contents)
95+
{
96+
if (oContent is Dictionary<string, object> content
97+
&& content.TryGetValue("parts", out var oParts)
98+
&& oParts is List<object> parts)
99+
{
100+
foreach (var oPart in parts)
101+
{
102+
if (oPart is Dictionary<string, object> part
103+
&& part.TryGetValue("inline_data", out var oInlineData)
104+
&& oInlineData is Dictionary<string, object> inlineData
105+
&& inlineData.TryGetValue("data", out var oData)
106+
&& oData is string data)
107+
{
108+
inlineData["data"] = $"({data.Length})";
109+
}
110+
}
111+
}
112+
}
113+
}
114+
Console.WriteLine(JSON.stringify(obj));
115+
```
116+
117+
This would be an equivalent implementation using System.Text.Json:
118+
119+
```csharp
120+
using System.Text.Json;
121+
122+
var jsonDocument = JsonDocument.Parse(json);
123+
var root = jsonDocument.RootElement;
124+
125+
if (root.TryGetProperty("contents", out var contentsElement)
126+
&& contentsElement.ValueKind == JsonValueKind.Array)
127+
{
128+
foreach (var contentElement in contentsElement.EnumerateArray())
129+
{
130+
if (contentElement.ValueKind == JsonValueKind.Object
131+
&& contentElement.TryGetProperty("parts", out var partsElement)
132+
&& partsElement.ValueKind == JsonValueKind.Array)
133+
{
134+
foreach (var partElement in partsElement.EnumerateArray())
135+
{
136+
if (partElement.ValueKind == JsonValueKind.Object
137+
&& partElement.TryGetProperty("inline_data", out var inlineDataElement)
138+
&& inlineDataElement.ValueKind == JsonValueKind.Object
139+
&& inlineDataElement.TryGetProperty("data", out var dataElement)
140+
&& dataElement.ValueKind == JsonValueKind.String)
141+
{
142+
var data = dataElement.GetString();
143+
// Note: System.Text.Json JsonDocument is read-only
144+
// To modify, you'd need to reconstruct the JSON or use JsonNode
145+
Console.WriteLine($"Data length: {data?.Length}");
146+
}
147+
}
148+
}
149+
}
150+
}
151+
```
152+
153+
But as it's a read-only data structure you'd need to reconstruct the JSON to modify it. To create an equivalent modified JSON for logging, you can use `JsonNode` for mutable operations:
154+
155+
```csharp
156+
using System.Text.Json;
157+
using System.Text.Json.Nodes;
158+
159+
var jsonNode = JsonNode.Parse(json);
160+
161+
if (jsonNode is JsonObject rootObj
162+
&& rootObj["contents"] is JsonArray contentsArray)
163+
{
164+
foreach (var contentNode in contentsArray)
165+
{
166+
if (contentNode is JsonObject contentObj
167+
&& contentObj["parts"] is JsonArray partsArray)
168+
{
169+
foreach (var partNode in partsArray)
170+
{
171+
if (partNode is JsonObject partObj
172+
&& partObj["inline_data"] is JsonObject inlineDataObj
173+
&& inlineDataObj["data"] is JsonValue dataValue
174+
&& dataValue.TryGetValue<string>(out var data))
175+
{
176+
// Modify the data for logging
177+
inlineDataObj["data"] = $"({data.Length})";
178+
}
179+
}
180+
}
181+
}
182+
}
183+
184+
// Output the modified JSON for logging
185+
Console.WriteLine(jsonNode.ToJsonString());
186+
```
187+
188+
30189
### Register JS Utils in ServiceStack.Text
31190

32191
JS Utils is already pre-configured in ServiceStack Web Apps to handle serializing & deserializing `object` types.

0 commit comments

Comments
 (0)