Skip to content

Commit b248818

Browse files
committed
修复字典类型的JSON转换器反序列化出现的多读问题。 🌈
1 parent 2bdb81f commit b248818

2 files changed

Lines changed: 114 additions & 18 deletions

File tree

Zongsoft.Core/src/Serialization/Json/Converters/DictionaryConverterFactory.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ private class ClassicDictionaryConverter(TextSerializationOptions options) : Jso
5151
public override IDictionary Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
5252
{
5353
string key = null;
54+
var depth = reader.CurrentDepth;
5455
IDictionary dictionary = type.IsAbstract ? new Dictionary<string, object>() : (IDictionary)Activator.CreateInstance(type);
5556

5657
while(reader.Read())
@@ -80,6 +81,10 @@ public override IDictionary Read(ref Utf8JsonReader reader, Type type, JsonSeria
8081
dictionary[key] = ObjectConverter.Default.Read(ref reader, typeof(object[]), options);
8182
break;
8283
}
84+
85+
//确保不会超读
86+
if(reader.TokenType == JsonTokenType.EndObject && reader.CurrentDepth == depth)
87+
break;
8388
}
8489

8590
return dictionary;
@@ -131,6 +136,7 @@ private class GenericDictionaryConverter<TKey, TValue>(TextSerializationOptions
131136
public override IDictionary<TKey, TValue> Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
132137
{
133138
TKey key = default;
139+
var depth = reader.CurrentDepth;
134140
var dictionary = new Dictionary<TKey, TValue>();
135141

136142
while(reader.Read())
@@ -163,6 +169,10 @@ public override IDictionary<TKey, TValue> Read(ref Utf8JsonReader reader, Type t
163169
dictionary[key] = Common.Convert.ConvertValue(ObjectConverter.Default.Read(ref reader, typeof(object[]), options), default(TValue));
164170
break;
165171
}
172+
173+
//确保不会超读
174+
if(reader.TokenType == JsonTokenType.EndObject && reader.CurrentDepth == depth)
175+
break;
166176
}
167177

168178
return dictionary;

Zongsoft.Core/test/Serialization/JsonSerializerTest.cs

Lines changed: 104 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public class JsonSerializerTest
1717
private const string STRING = nameof(String);
1818

1919
[Fact]
20-
public void TestSerialize()
20+
public void TestModel()
2121
{
2222
var user = CreateUser();
2323
var json = Serializer.Json.Serialize(user);
@@ -41,7 +41,7 @@ public void TestSerialize()
4141
}
4242

4343
[Fact]
44-
public void TestSerializeDataDictionary()
44+
public void TestDataDictionary()
4545
{
4646
var dictionary = DataDictionary.GetDictionary(CreateUser());
4747
var json = Serializer.Json.Serialize(dictionary);
@@ -53,7 +53,7 @@ public void TestSerializeDataDictionary()
5353
}
5454

5555
[Fact]
56-
public void TestSerializeClassicDictionary()
56+
public void TestClassicDictionary()
5757
{
5858
var dictionary = new Hashtable
5959
{
@@ -110,7 +110,7 @@ public void TestSerializeClassicDictionary()
110110
}
111111

112112
[Fact]
113-
public void TestSerializeGenericDictionary1()
113+
public void TestGenericDictionary1()
114114
{
115115
var dictionary = new Dictionary<string, object>
116116
{
@@ -166,7 +166,7 @@ public void TestSerializeGenericDictionary1()
166166
}
167167

168168
[Fact]
169-
public void TestSerializeGenericDictionary2()
169+
public void TestGenericDictionary2()
170170
{
171171
var dictionary = new Dictionary<string, Gender>()
172172
{
@@ -189,28 +189,94 @@ public void TestSerializeGenericDictionary2()
189189
}
190190

191191
[Fact]
192-
public void TestSerializeTypedGenericDictionary()
192+
public void TestTypedGenericDictionary()
193193
{
194-
var dictionary = new Dictionary<string, Gender>()
194+
var source = new Dictionary<string, Gender>()
195195
{
196196
{ nameof(Gender.Male), Gender.Male },
197197
{ nameof(Gender.Female), Gender.Female },
198198
};
199199

200-
var json = Serializer.Json.Serialize(dictionary, Serializer.Json.Options.Typified());
200+
var json = Serializer.Json.Serialize(source, Serializer.Json.Options.Typified());
201201
Assert.NotNull(json);
202202
Assert.NotEmpty(json);
203203

204-
var result = Serializer.Json.Deserialize<Dictionary<string, Gender>>(json, Serializer.Json.Options.Typified());
205-
Assert.NotNull(result);
206-
Assert.NotEmpty(result);
207-
Assert.Equal(2, result.Count);
208-
Assert.True(result.TryGetValue(nameof(Gender.Male), out var male));
204+
var target = Serializer.Json.Deserialize<Dictionary<string, Gender>>(json, Serializer.Json.Options.Typified());
205+
Assert.NotNull(target);
206+
Assert.NotEmpty(target);
207+
Assert.Equal(2, target.Count);
208+
Assert.True(target.TryGetValue(nameof(Gender.Male), out var male));
209209
Assert.Equal(Gender.Male, male);
210-
Assert.True(result.TryGetValue(nameof(Gender.Female), out var female));
210+
Assert.True(target.TryGetValue(nameof(Gender.Female), out var female));
211211
Assert.Equal(Gender.Female, female);
212212
}
213213

214+
[Fact]
215+
public void TestWrappedGenericDictionary()
216+
{
217+
var source = new GenericDictionaryWrapper()
218+
{
219+
Identifier = 100,
220+
Name = $"{nameof(GenericDictionaryWrapper)}.{nameof(GenericDictionaryWrapper.Name)}",
221+
Tags = new Dictionary<string, GenericDictionaryWrapper.Tag>()
222+
{
223+
{ "A", new("default", "Tag#1") },
224+
{ "B", new("default", "Tag#2") },
225+
{ "C", new("default", "Tag#3") },
226+
},
227+
};
228+
229+
var json = Serializer.Json.Serialize(source);
230+
Assert.NotNull(json);
231+
Assert.NotEmpty(json);
232+
233+
var target = Serializer.Json.Deserialize<GenericDictionaryWrapper>(json);
234+
Assert.NotNull(target);
235+
Assert.NotNull(target.Tags);
236+
Assert.NotEmpty(target.Tags);
237+
Assert.Equal(source.Tags.Count, target.Tags.Count);
238+
239+
foreach(var entry in source.Tags)
240+
{
241+
Assert.True(target.Tags.TryGetValue(entry.Key, out var tag));
242+
Assert.Equal(entry.Value.Scope, tag.Scope);
243+
Assert.Equal(entry.Value.Value, tag.Value);
244+
}
245+
}
246+
247+
[Fact]
248+
public void TestWrappedTypedGenericDictionary()
249+
{
250+
var source = new GenericDictionaryWrapper()
251+
{
252+
Identifier = 100,
253+
Name = $"{nameof(GenericDictionaryWrapper)}.{nameof(GenericDictionaryWrapper.Name)}",
254+
Tags = new Dictionary<string, GenericDictionaryWrapper.Tag>()
255+
{
256+
{ "A", new("default", "Tag#1") },
257+
{ "B", new("default", "Tag#2") },
258+
{ "C", new("default", "Tag#3") },
259+
},
260+
};
261+
262+
var json = Serializer.Json.Serialize(source, Serializer.Json.Options.Typified());
263+
Assert.NotNull(json);
264+
Assert.NotEmpty(json);
265+
266+
var target = Serializer.Json.Deserialize<GenericDictionaryWrapper>(json, Serializer.Json.Options.Typified());
267+
Assert.NotNull(target);
268+
Assert.NotNull(target.Tags);
269+
Assert.NotEmpty(target.Tags);
270+
Assert.Equal(source.Tags.Count, target.Tags.Count);
271+
272+
foreach(var entry in source.Tags)
273+
{
274+
Assert.True(target.Tags.TryGetValue(entry.Key, out var tag));
275+
Assert.Equal(entry.Value.Scope, tag.Scope);
276+
Assert.Equal(entry.Value.Value, tag.Value);
277+
}
278+
}
279+
214280
[Fact]
215281
public void TestDeserialize()
216282
{
@@ -370,11 +436,11 @@ public void TestDeserializeGenericDictionary()
370436
Assert.Null(array[2]);
371437
}
372438

373-
private static IUser CreateUser() => Model.Build<IUser>(p =>
439+
private static IUser CreateUser() => Model.Build<IUser>(user =>
374440
{
375-
p.Identifier = new Zongsoft.Components.Identifier(typeof(IUser), 100);
376-
p.Name = "Popeye";
377-
p.Nickname = "钟少";
441+
user.Identifier = new Zongsoft.Components.Identifier(typeof(IUser), 100);
442+
user.Name = "Popeye";
443+
user.Nickname = "钟少";
378444
});
379445

380446
private static Credential CreateCredential() => new()
@@ -385,6 +451,26 @@ private static IUser CreateUser() => Model.Build<IUser>(p =>
385451
User = CreateUser(),
386452
};
387453

454+
public class GenericDictionaryWrapper
455+
{
456+
public int Identifier { get; set; }
457+
public string Name { get; set; }
458+
public Dictionary<string, Tag> Tags { get; set; }
459+
460+
public struct Tag
461+
{
462+
public Tag(string scope, string value)
463+
{
464+
this.Scope = scope;
465+
this.Value = value;
466+
}
467+
468+
public string Scope { get; set; }
469+
public string Value { get; set; }
470+
public readonly override string ToString() => $"{this.Scope}:{this.Value}";
471+
}
472+
}
473+
388474
public class Credential : IEquatable<Credential>
389475
{
390476
public string CredentialId { get; set; }

0 commit comments

Comments
 (0)