Skip to content

Commit 8ff8754

Browse files
committed
Fix API break: public API must not expose JsonElement objects
This changes deserialization to the way how it was with Json.Net: Only .net primitive types are exposed publicly
1 parent bfad0cd commit 8ff8754

File tree

2 files changed

+147
-7
lines changed

2 files changed

+147
-7
lines changed

src/ElectronNET.API/API/IpcMain.cs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,32 @@
1-
using ElectronNET.API.Serialization;
2-
using System;
3-
using System.Collections.Generic;
4-
using System.Linq;
5-
using System.Text.Json;
6-
using System.Threading.Tasks;
7-
81
namespace ElectronNET.API
92
{
3+
using System;
4+
using System.Diagnostics;
5+
using System.Linq;
6+
using System.Text.Json;
7+
using System.Text.Json.Serialization;
8+
using System.Threading.Tasks;
9+
using ElectronNET.Serialization;
10+
1011
/// <summary>
1112
/// Communicate asynchronously from the main process to renderer processes.
1213
/// </summary>
1314
public sealed class IpcMain
1415
{
1516
private static IpcMain _ipcMain;
1617
private static object _syncRoot = new object();
18+
private static readonly JsonSerializerOptions BoxedObjectSerializationOptions = new JsonSerializerOptions
19+
{
20+
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
21+
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
22+
WriteIndented = false,
23+
Converters =
24+
{
25+
new JsonStringEnumConverter(JsonNamingPolicy.CamelCase),
26+
new JsonToBoxedPrimitivesConverter(),
27+
}
28+
};
29+
1730

1831
internal IpcMain()
1932
{
@@ -65,6 +78,7 @@ public async Task On(string channel, Action<object> listener)
6578

6679
private static List<object> FormatArguments(JsonElement args)
6780
{
81+
var objectArray = args.Deserialize<object[]>(BoxedObjectSerializationOptions).ToList();
6882
var objectArray = args.Deserialize<object[]>(ElectronJson.Options).ToList();
6983
objectArray.RemoveAll(item => item is null);
7084
return objectArray;
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
namespace ElectronNET.Serialization
2+
{
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Text.Json;
6+
using System.Text.Json.Serialization;
7+
8+
public sealed class JsonToBoxedPrimitivesConverter : JsonConverter<object>
9+
{
10+
public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
11+
{
12+
return ReadValue(ref reader);
13+
}
14+
15+
private static object ReadValue(ref Utf8JsonReader r)
16+
{
17+
switch (r.TokenType)
18+
{
19+
case JsonTokenType.StartObject:
20+
21+
var obj = new Dictionary<string, object>();
22+
while (r.Read())
23+
{
24+
if (r.TokenType == JsonTokenType.EndObject)
25+
{
26+
return obj;
27+
}
28+
29+
if (r.TokenType != JsonTokenType.PropertyName)
30+
{
31+
throw new JsonException("Expected property name.");
32+
}
33+
34+
string name = r.GetString()!;
35+
if (!r.Read())
36+
{
37+
throw new JsonException("Unexpected end while reading property value.");
38+
}
39+
40+
obj[name] = ReadValue(ref r);
41+
}
42+
43+
throw new JsonException("Unexpected end while reading object.");
44+
45+
case JsonTokenType.StartArray:
46+
47+
var list = new List<object>();
48+
while (r.Read())
49+
{
50+
if (r.TokenType == JsonTokenType.EndArray)
51+
{
52+
return list;
53+
}
54+
55+
list.Add(ReadValue(ref r));
56+
}
57+
58+
throw new JsonException("Unexpected end while reading array.");
59+
60+
case JsonTokenType.True: return true;
61+
case JsonTokenType.False: return false;
62+
case JsonTokenType.Null: return null;
63+
64+
case JsonTokenType.Number:
65+
66+
if (r.TryGetInt32(out int i))
67+
{
68+
return i;
69+
}
70+
71+
if (r.TryGetInt64(out long l))
72+
{
73+
return l;
74+
}
75+
76+
if (r.TryGetDouble(out double d))
77+
{
78+
return d;
79+
}
80+
81+
return r.GetDecimal();
82+
83+
case JsonTokenType.String:
84+
85+
string s = r.GetString()!;
86+
87+
if (DateTimeOffset.TryParse(s, out var dto))
88+
{
89+
return dto;
90+
}
91+
92+
if (DateTime.TryParse(s, out var dt))
93+
{
94+
return dt;
95+
}
96+
97+
if (TimeSpan.TryParse(s, out var ts))
98+
{
99+
return ts;
100+
}
101+
102+
if (Guid.TryParse(s, out var g))
103+
{
104+
return g;
105+
}
106+
107+
return s;
108+
109+
default:
110+
throw new JsonException($"Unsupported token {r.TokenType}");
111+
}
112+
}
113+
114+
public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
115+
{
116+
if (value is null)
117+
{
118+
writer.WriteNullValue();
119+
return;
120+
}
121+
122+
writer.WriteStartObject();
123+
writer.WriteEndObject();
124+
}
125+
}
126+
}

0 commit comments

Comments
 (0)