Skip to content

Commit 7a191f3

Browse files
Oito654Octavius
andauthored
Fix error on rendering JsonObjects and null values. Another refactorings (#503)
* Fix error on rendering JsonObjects and null values. Another refactorings * removing .git.bak folder * Removing unnecessary package and add better error visualization --------- Co-authored-by: Octavius <octavius.alimari@eritel.com.br>
1 parent 7c4ec5a commit 7a191f3

File tree

3 files changed

+196
-112
lines changed

3 files changed

+196
-112
lines changed

CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/JsonTreeView/Examples/JsonTreeViewExample1.razor

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,21 @@
3131
'Vietnamese',
3232
'Caucasian'
3333
],
34+
'Family': {
35+
'PatientRecordType': 'v4.0.8',
36+
'DoctorId': '8F704CD5-3CCE-4CC0-957C-2BC98DC06E42',
37+
'PatientId': '0000-0002-7',
38+
'Birthdate': '2003-06-12T00:00:00Z',
39+
'UpdateDate': '2025-03-18T07:12:27.2502767-05:00',
40+
'Races': [
41+
'Caucasian'
42+
],
43+
'Family': null,
44+
'Status': 'AV',
45+
'Gender': 'F',
46+
'Active': false,
47+
'Type': 'Normal'
48+
},
3449
'Status': 'AV',
3550
'Gender': 'M',
3651
'Active': true,
Lines changed: 6 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,123 +1,17 @@
11
@namespace MudExtensions
22
@using System.Text.Json;
3-
@using System.Text.Json.Nodes
3+
@using System.Text.Json.Nodes;
44

55
@if (Node is JsonObject)
66
{
7-
@* If sorting is enabled, sort by key *@
8-
var nodes = Sorted ? Node.AsObject().OrderBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value) : Node.AsObject().ToDictionary(x => x.Key, x => x.Value);
9-
@* Go through each item *@
10-
foreach (var child in nodes)
11-
{
12-
if (child.Value is JsonValue)
13-
{
14-
@* Get the type of value in this node *@
15-
var valueKind = child.Value.AsValue().GetValue<JsonElement>().ValueKind;
16-
switch (valueKind)
17-
{
18-
case JsonValueKind.String:
19-
var str = child.Value.AsValue().GetValue<string>();
20-
@* Could be a date *@
21-
if (DateTime.TryParse(str, out DateTime date))
22-
{
23-
<MudTreeViewItem T="string" Text="@child.Key" Icon="@Icons.Material.Filled.DateRange" EndText="@date.ToString()"></MudTreeViewItem>
24-
}
25-
@* Could be a GUID *@
26-
else if (Guid.TryParse(str, out Guid guid))
27-
{
28-
<MudTreeViewItem T="string" Text="@child.Key" Icon="@Icons.Material.Filled.Key" EndText="@str.ToUpperInvariant()"></MudTreeViewItem>
29-
}
30-
@* Fall back to string *@
31-
else
32-
{
33-
<MudTreeViewItem T="string" Text="@child.Key" Icon="@Icons.Material.Filled.TextSnippet" EndText="@str"></MudTreeViewItem>
34-
}
35-
break;
36-
case JsonValueKind.Number:
37-
JsonValue jsonVal = child.Value.AsValue();
38-
string endText = string.Empty;
39-
@* We try for int first, because an int can always be converted to double but not the other way around*@
40-
if (jsonVal.TryGetValue<int>(out int intVal))
41-
{
42-
endText = intVal.ToString();
43-
}
44-
else if (jsonVal.TryGetValue<double>(out double doubleVal))
45-
{
46-
endText = doubleVal.ToString();
47-
}
48-
<MudTreeViewItem T="string" Text="@child.Key" Icon="@Icons.Material.Filled.Numbers" EndText="@endText"></MudTreeViewItem>
49-
break;
50-
case JsonValueKind.True:
51-
<MudTreeViewItem T="string" Text="@child.Key" Icon="@Icons.Material.Filled.CheckBox" EndText="true"></MudTreeViewItem>
52-
break;
53-
case JsonValueKind.False:
54-
<MudTreeViewItem T="string" Text="@child.Key" Icon="@Icons.Material.Filled.CheckBoxOutlineBlank" EndText="false"></MudTreeViewItem>
55-
break;
56-
}
57-
}
58-
else if (child.Value is JsonArray)
59-
{
60-
<MudTreeViewItem T="string" IconColor="Color.Primary" Icon="@Icons.Material.Filled.Folder" Text="@child.Key" EndTextClass="mud-primary-text" EndText="(Array)">
61-
@* Iterate each array element *@
62-
<MudJsonTreeViewNode Node="@child.Value" Sorted="@Sorted" />
63-
</MudTreeViewItem>
64-
}
65-
}
66-
}
67-
else if (Node is JsonArray)
68-
{
69-
var count = 0;
70-
@* Iterate each array element *@
71-
foreach (var child in Node.AsArray())
7+
var node = Sorted ? Node.AsObject().OrderBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value) : Node.AsObject().ToDictionary(x => x.Key, x => x.Value);
8+
9+
foreach (var item in node)
7210
{
73-
count++;
74-
<MudTreeViewItem T="string" IconColor="Color.Primary" Icon="@Icons.Material.Filled.Folder" EndTextClass="mud-primary-text" EndText="@($"(Item {count})")">
75-
<MudJsonTreeViewNode Node="@child" Sorted="@Sorted" />
76-
</MudTreeViewItem>
11+
@RenderJsonItem(item)
7712
}
7813
}
7914
else if (Node is JsonNode)
8015
{
81-
var valueKind = Node.AsValue().GetValue<JsonElement>().ValueKind;
82-
switch (valueKind)
83-
{
84-
case JsonValueKind.String:
85-
var str = Node.AsValue().GetValue<string>();
86-
@* Could be a date *@
87-
if (DateTime.TryParse(str, out DateTime date))
88-
{
89-
<MudTreeViewItem T="string" Icon="@Icons.Material.Filled.DateRange" EndText="@date.ToString()"></MudTreeViewItem>
90-
}
91-
@* Could be a GUID *@
92-
else if (Guid.TryParse(str, out Guid guid))
93-
{
94-
<MudTreeViewItem T="string" Icon="@Icons.Material.Filled.Key" EndText="@str.ToUpperInvariant()"></MudTreeViewItem>
95-
}
96-
@* Fall back to string *@
97-
else
98-
{
99-
<MudTreeViewItem T="string" Icon="@Icons.Material.Filled.TextSnippet" EndText="@str"></MudTreeViewItem>
100-
}
101-
break;
102-
case JsonValueKind.Number:
103-
JsonValue jsonVal = Node.AsValue();
104-
string endText = string.Empty;
105-
@* We try for int first, because an int can always be converted to double but not the other way around*@
106-
if (jsonVal.TryGetValue<int>(out int intVal))
107-
{
108-
endText = intVal.ToString();
109-
}
110-
else if (jsonVal.TryGetValue<double>(out double doubleVal))
111-
{
112-
endText = doubleVal.ToString();
113-
}
114-
<MudTreeViewItem T="string" Icon="@Icons.Material.Filled.Numbers" EndText="@endText"></MudTreeViewItem>
115-
break;
116-
case JsonValueKind.True:
117-
<MudTreeViewItem T="string" Icon="@Icons.Material.Filled.CheckBox" EndText="true"></MudTreeViewItem>
118-
break;
119-
case JsonValueKind.False:
120-
<MudTreeViewItem T="string" Icon="@Icons.Material.Filled.CheckBoxOutlineBlank" EndText="false"></MudTreeViewItem>
121-
break;
122-
}
16+
@RenderJsonItem(Node)
12317
}

CodeBeam.MudBlazor.Extensions/Components/JsonTreeView/MudJsonTreeViewNode.razor.cs

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
using Microsoft.AspNetCore.Components;
2+
using Microsoft.AspNetCore.Components.Rendering;
3+
using MudBlazor;
4+
using System.Text.Json;
25
using System.Text.Json.Nodes;
36

47
namespace MudExtensions;
@@ -22,4 +25,176 @@ public partial class MudJsonTreeViewNode : ComponentBase
2225
/// </summary>
2326
[Parameter]
2427
public bool Sorted { get; set; }
28+
29+
30+
/// <summary>
31+
/// Gets or sets a children text.
32+
/// </summary>
33+
[Parameter]
34+
public string Text { get; set; } = string.Empty;
35+
36+
public RenderFragment RenderJsonItem(KeyValuePair<string, JsonNode?> item) => builder =>
37+
{
38+
try
39+
{
40+
if (item.Value is JsonValue)
41+
{
42+
var value = item.Value.AsValue();
43+
var valueType = value.GetValue<JsonElement>().ValueKind;
44+
GenerateItemBasedOnType(valueType, item.Key, value, builder);
45+
}
46+
else if (item.Value is JsonArray)
47+
GenerateNestedComponent(builder, item, Icons.Material.Filled.DataArray, "(Array)");
48+
else if (item.Value is JsonObject)
49+
GenerateNestedComponent(builder, item, Icons.Material.Filled.DataObject, "(Object)");
50+
else if (item.Value is null)
51+
GenerateComponent(builder, item.Key, "null", Icons.Material.Filled.Block);
52+
}
53+
catch (Exception ex)
54+
{
55+
builder.OpenComponent<MudAlert>(0);
56+
builder.AddAttribute(1, "Severity", Severity.Warning);
57+
builder.AddAttribute(2, "ChildContent", (RenderFragment)(builder2 =>
58+
{
59+
builder2.AddContent(3, $"Error rendering JSON item: {ex.Message}");
60+
}));
61+
builder.CloseComponent();
62+
}
63+
};
64+
65+
public RenderFragment RenderJsonItem(JsonNode? node) => builder =>
66+
{
67+
try
68+
{
69+
if (node is JsonValue)
70+
{
71+
var value = node.AsValue();
72+
var valueType = value.GetValue<JsonElement>().ValueKind;
73+
GenerateItemBasedOnType(valueType, Text, value, builder);
74+
}
75+
else if (node is JsonArray)
76+
GenerateNestedComponent(builder, node, Icons.Material.Filled.DataArray, "(Array)");
77+
else if (node is JsonObject)
78+
GenerateNestedComponent(builder, node, Icons.Material.Filled.DataObject, "(Object)");
79+
else if (node is null)
80+
GenerateComponent(builder, node.ToString(), "null", Icons.Material.Filled.Block);
81+
}
82+
catch (Exception ex)
83+
{
84+
builder.OpenComponent<MudAlert>(0);
85+
builder.AddAttribute(2, "Severity", Severity.Warning);
86+
builder.AddContent(1, $"Error rendering JSON item: {ex.Message}");
87+
builder.CloseComponent();
88+
}
89+
};
90+
91+
void GenerateItemBasedOnType(JsonValueKind valueType, string text, JsonValue? value, RenderTreeBuilder builder)
92+
{
93+
switch (valueType)
94+
{
95+
case JsonValueKind.String:
96+
var str = value?.GetValue<string>();
97+
if (DateTime.TryParse(str, out DateTime date))
98+
GenerateComponent(builder, text, date.ToString(), Icons.Material.Filled.DateRange);
99+
else if (Guid.TryParse(str, out Guid guid))
100+
GenerateComponent(builder, text, str.ToUpperInvariant(), Icons.Material.Filled.Key);
101+
else
102+
GenerateComponent(builder, text, str, Icons.Material.Filled.TextSnippet);
103+
break;
104+
105+
case JsonValueKind.Number:
106+
string endText = string.Empty;
107+
if (value.TryGetValue<int>(out int intVal))
108+
{
109+
endText = intVal.ToString();
110+
}
111+
else if (value.TryGetValue<double>(out double doubleVal))
112+
{
113+
endText = doubleVal.ToString();
114+
}
115+
GenerateComponent(builder, text, endText, Icons.Material.Filled.Numbers);
116+
break;
117+
case JsonValueKind.True:
118+
GenerateComponent(builder, text, "true", Icons.Material.Filled.CheckBox);
119+
break;
120+
case JsonValueKind.False:
121+
GenerateComponent(builder, text, "false", Icons.Material.Filled.CheckBoxOutlineBlank);
122+
break;
123+
}
124+
}
125+
126+
void GenerateComponent(RenderTreeBuilder builder, string text, string endText, string icon)
127+
{
128+
builder.OpenComponent<MudTreeViewItem<string>>(0);
129+
builder.AddAttribute(1, "Text", text);
130+
builder.AddAttribute(2, "Icon", icon);
131+
builder.AddAttribute(3, "EndText", endText);
132+
builder.CloseComponent();
133+
}
134+
135+
void GenerateNestedComponent(RenderTreeBuilder builder, KeyValuePair<string, JsonNode?> item, string icon, string endText)
136+
{
137+
builder.OpenComponent<MudTreeViewItem<string>>(0);
138+
builder.AddAttribute(1, "Text", item.Key);
139+
builder.AddAttribute(2, "Icon", icon);
140+
builder.AddAttribute(3, "IconColor", Color.Primary);
141+
builder.AddAttribute(4, "EndText", endText);
142+
builder.AddAttribute(5, "EndTextClass", "mud-primary-text");
143+
builder.AddAttribute(6, "ChildContent", (RenderFragment)(childBuilder =>
144+
{
145+
if (item.Value.GetValueKind() is JsonValueKind.Array)
146+
{
147+
int count = 0;
148+
foreach (var childItem in item.Value.AsArray())
149+
{
150+
count++;
151+
childBuilder.OpenComponent<MudJsonTreeViewNode>(0);
152+
childBuilder.AddAttribute(1, "Node", childItem);
153+
childBuilder.AddAttribute(2, "Text", $"{count - 1}");
154+
childBuilder.CloseComponent();
155+
}
156+
}
157+
else
158+
{
159+
childBuilder.OpenComponent<MudJsonTreeViewNode>(0);
160+
childBuilder.AddAttribute(1, "Node", item.Value);
161+
childBuilder.AddAttribute(2, "Text", $"{item.Key}");
162+
childBuilder.CloseComponent();
163+
}
164+
}));
165+
builder.CloseComponent();
166+
}
167+
168+
void GenerateNestedComponent(RenderTreeBuilder builder, JsonNode? item, string icon, string endText)
169+
{
170+
builder.OpenComponent<MudTreeViewItem<string>>(0);
171+
builder.AddAttribute(1, "Text", item);
172+
builder.AddAttribute(2, "Icon", icon);
173+
builder.AddAttribute(3, "IconColor", Color.Primary);
174+
builder.AddAttribute(4, "EndText", endText);
175+
builder.AddAttribute(5, "EndTextClass", "mud-primary-text");
176+
builder.AddAttribute(6, "ChildContent", (RenderFragment)(childBuilder =>
177+
{
178+
if (item.GetValueKind() is JsonValueKind.Array)
179+
{
180+
int count = 0;
181+
foreach (var childItem in item.AsArray())
182+
{
183+
count++;
184+
childBuilder.OpenComponent<MudJsonTreeViewNode>(0);
185+
childBuilder.AddAttribute(1, "Node", childItem);
186+
childBuilder.AddAttribute(2, "Text", $"{count - 1}");
187+
childBuilder.CloseComponent();
188+
}
189+
}
190+
else
191+
{
192+
childBuilder.OpenComponent<MudJsonTreeViewNode>(0);
193+
childBuilder.AddAttribute(1, "Node", item);
194+
childBuilder.AddAttribute(2, "Text", $"{item}");
195+
childBuilder.CloseComponent();
196+
}
197+
}));
198+
builder.CloseComponent();
199+
}
25200
}

0 commit comments

Comments
 (0)