Skip to content

Commit 894e27c

Browse files
authored
feat(QueryPageOptions): SearchModel support serialize (#7327)
* refactor: 代码重构增加 type 标识类型 * test: 更新单元测试 * test: 补充单元测试 * test: 增加单元测试提高覆盖率 * chore: bump version 10.1.4-beta07
1 parent 258c546 commit 894e27c

5 files changed

Lines changed: 152 additions & 16 deletions

File tree

src/BootstrapBlazor/BootstrapBlazor.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk.Razor">
22

33
<PropertyGroup>
4-
<Version>10.1.3</Version>
4+
<Version>10.1.4-beta07</Version>
55
</PropertyGroup>
66

77
<ItemGroup>

src/BootstrapBlazor/Converter/JsonFilterKeyValueActionConverter.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,7 @@ public sealed class JsonFilterKeyValueActionConverter : JsonConverter<FilterKeyV
4242
action.FieldKey = reader.GetString();
4343
break;
4444
case "fieldValueType":
45-
var typeName = reader.GetString();
46-
if (!string.IsNullOrEmpty(typeName))
47-
{
48-
fieldValueType = Type.GetType(typeName);
49-
}
45+
fieldValueType = TypeExtensions.GetSafeType(reader.GetString());
5046
break;
5147
case "fieldValue":
5248
if (fieldValueType != null)
@@ -89,7 +85,7 @@ public override void Write(Utf8JsonWriter writer, FilterKeyValueAction value, Js
8985
writer.WriteStartObject();
9086
writer.WriteString("fieldKey", value.FieldKey);
9187

92-
writer.WriteString("fieldValueType", value.FieldValue?.GetType().FullName);
88+
WriteFieldValueType(writer, value, options);
9389

9490
writer.WritePropertyName("fieldValue");
9591
writer.WriteRawValue(JsonSerializer.Serialize(value.FieldValue, options));
@@ -109,4 +105,13 @@ public override void Write(Utf8JsonWriter writer, FilterKeyValueAction value, Js
109105

110106
writer.WriteEndObject();
111107
}
108+
109+
private static void WriteFieldValueType(Utf8JsonWriter writer, FilterKeyValueAction value, JsonSerializerOptions options)
110+
{
111+
if (value.FieldValue != null)
112+
{
113+
var type = value.FieldValue.GetType();
114+
writer.WriteString("fieldValueType", type.AssemblyQualifiedName);
115+
}
116+
}
112117
}

src/BootstrapBlazor/Converter/JsonQueryPageOptionConverter.cs

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,7 @@ public sealed class JsonQueryPageOptionsConverter : JsonConverter<QueryPageOptio
7373
else if (propertyName == "searchModel")
7474
{
7575
reader.Read();
76-
var val = JsonSerializer.Deserialize<object>(ref reader, options);
77-
if (val != null)
78-
{
79-
ret.SearchModel = val;
80-
}
76+
ReadSearchModel(ref reader, ret, options);
8177
}
8278
else if (propertyName == "pageIndex")
8379
{
@@ -229,8 +225,7 @@ public override void Write(Utf8JsonWriter writer, QueryPageOptions value, JsonSe
229225
}
230226
if (value.SearchModel != null)
231227
{
232-
writer.WritePropertyName("searchModel");
233-
writer.WriteRawValue(JsonSerializer.Serialize(value.SearchModel, options));
228+
WriteSearchModel(writer, value.SearchModel, options);
234229
}
235230
if (value.PageIndex > 1)
236231
{
@@ -302,4 +297,52 @@ public override void Write(Utf8JsonWriter writer, QueryPageOptions value, JsonSe
302297
}
303298
writer.WriteEndObject();
304299
}
300+
301+
private static void WriteSearchModel(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
302+
{
303+
writer.WriteStartObject("searchModel");
304+
writer.WriteString("type", value.GetType().AssemblyQualifiedName);
305+
writer.WritePropertyName("value");
306+
writer.WriteRawValue(JsonSerializer.Serialize(value, options));
307+
writer.WriteEndObject();
308+
}
309+
310+
private static void ReadSearchModel(ref Utf8JsonReader reader, QueryPageOptions value, JsonSerializerOptions options)
311+
{
312+
if (reader.TokenType == JsonTokenType.StartObject)
313+
{
314+
while (reader.Read())
315+
{
316+
if (reader.TokenType == JsonTokenType.EndObject)
317+
{
318+
break;
319+
}
320+
321+
if (reader.TokenType == JsonTokenType.PropertyName)
322+
{
323+
var propertyName = reader.GetString();
324+
if (propertyName == "type")
325+
{
326+
reader.Read();
327+
Type? type = TypeExtensions.GetSafeType(reader.GetString());
328+
329+
reader.Read();
330+
propertyName = reader.GetString();
331+
if (propertyName == "value")
332+
{
333+
reader.Read();
334+
if (type != null)
335+
{
336+
value.SearchModel = JsonSerializer.Deserialize(ref reader, type, options);
337+
}
338+
else
339+
{
340+
value.SearchModel = JsonSerializer.Deserialize<object>(ref reader, options);
341+
}
342+
}
343+
}
344+
}
345+
}
346+
}
347+
}
305348
}

src/BootstrapBlazor/Extensions/TypeExtensions.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Licensed to the .NET Foundation under one or more agreements.
1+
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the Apache 2.0 License
33
// See the LICENSE file in the project root for more information.
44
// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
@@ -64,4 +64,20 @@ void EnsureNoAuthenticationSchemeSpecified()
6464
public static string GetUniqueTypeName(this Type type) => type.IsCollectible
6565
? $"{type.FullName}-{type.TypeHandle.Value}"
6666
: $"{type.FullName}";
67+
68+
69+
/// <summary>
70+
/// 通过 typeName 参数安全获取 Type 实例
71+
/// </summary>
72+
/// <param name="typeName"></param>
73+
/// <returns></returns>
74+
public static Type? GetSafeType(string? typeName)
75+
{
76+
Type? type = null;
77+
if (!string.IsNullOrEmpty(typeName))
78+
{
79+
type = Type.GetType(typeName, throwOnError: false);
80+
}
81+
return type;
82+
}
6783
}

test/UnitTest/Extensions/QueryPageOptionsExtensionsTest.cs

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ public async Task Serialize_Ok()
182182
IsTriggerByPagination = true,
183183
IsPage = true,
184184
IsVirtualScroll = true,
185-
SearchModel = new { Name = "Test1", Count = 2 }
185+
SearchModel = new Foo { Name = "Test1", Count = 2 }
186186
};
187187

188188
model.Filters.Add(cut.Instance);
@@ -196,6 +196,11 @@ public async Task Serialize_Ok()
196196
var expected = JsonSerializer.Deserialize<QueryPageOptions>(payload);
197197
Assert.NotNull(expected);
198198
Assert.Equal("SearchText", expected.SearchText);
199+
200+
var foo = expected.SearchModel as Foo;
201+
Assert.NotNull(foo);
202+
Assert.Equal("Test1", foo.Name);
203+
199204
Assert.Equal("Name1", expected.SortName);
200205
Assert.Equal(3, expected.StartIndex);
201206
Assert.Equal(4, expected.PageIndex);
@@ -216,6 +221,73 @@ public async Task Serialize_Ok()
216221
Assert.Equal(2, expected.AdvancedSortList.Count);
217222
}
218223

224+
[Fact]
225+
public void SearchModel_Serialize()
226+
{
227+
var model = new QueryPageOptions
228+
{
229+
SearchModel = new { Name = "Test1", Count = 2 }
230+
};
231+
var payload = JsonSerializer.Serialize(model);
232+
var expected = JsonSerializer.Deserialize<QueryPageOptions>(payload);
233+
234+
Assert.NotNull(expected);
235+
Assert.NotNull(expected.SearchModel);
236+
}
237+
238+
[Fact]
239+
public void SearchModel_Serialize_TableSearchModel()
240+
{
241+
var model = new QueryPageOptions
242+
{
243+
SearchModel = new FooSearchModel { Name = "Test1" }
244+
};
245+
var payload = JsonSerializer.Serialize(model);
246+
var expected = JsonSerializer.Deserialize<QueryPageOptions>(payload);
247+
248+
Assert.NotNull(expected);
249+
Assert.NotNull(expected.SearchModel);
250+
Assert.Equal("FooSearchModel", expected.SearchModel.GetType().Name);
251+
}
252+
253+
[Fact]
254+
public void SearchModel_Serialize_NullType()
255+
{
256+
var model = new QueryPageOptions
257+
{
258+
SearchModel = new FooSearchModel { Name = "Test1" }
259+
};
260+
var payload = JsonSerializer.Serialize(model);
261+
262+
// 更改为错误的类型
263+
payload = payload.Replace("FooSearchModel", "FooSearchModel1");
264+
var expected = JsonSerializer.Deserialize<QueryPageOptions>(payload);
265+
266+
Assert.NotNull(expected);
267+
Assert.NotNull(expected.SearchModel);
268+
Assert.Equal("JsonElement", expected.SearchModel.GetType().Name);
269+
}
270+
271+
private class FooSearchModel : ITableSearchModel
272+
{
273+
public string? Name { get; set; }
274+
275+
public IEnumerable<IFilterAction> GetSearches()
276+
{
277+
var ret = new List<IFilterAction>();
278+
if (!string.IsNullOrEmpty(Name))
279+
{
280+
ret.Add(new SearchFilterAction(nameof(Foo.Name), Name));
281+
}
282+
return ret;
283+
}
284+
285+
public void Reset()
286+
{
287+
Name = null;
288+
}
289+
}
290+
219291
[Fact]
220292
public void SerializeFilterAction_Ok()
221293
{

0 commit comments

Comments
 (0)