Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit814fb1b

Browse files
author
Sychev Vadim
authored
Add DictionaryKeyPolicy support for EnumConverter [#47765] (#54429)
* Add DictionaryKeyPolicy support for EnumConverter [#47765]* Moved DictionaryKeyPolicy parsing code to WriteWithQuotes [#47765]* Refactored the bugfix in accordance to the comments (#47765)* Made few minor corrections (#47765)
1 parent70eec27 commit814fb1b

File tree

2 files changed

+158
-14
lines changed

2 files changed

+158
-14
lines changed

‎src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs‎

Lines changed: 63 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ internal sealed class EnumConverter<T> : JsonConverter<T>
2525

2626
privatereadonlyConcurrentDictionary<ulong,JsonEncodedText>_nameCache;
2727

28+
privateConcurrentDictionary<ulong,JsonEncodedText>?_dictionaryKeyPolicyCache;
29+
2830
// This is used to prevent flooding the cache due to exponential bitwise combinations of flags.
2931
// Since multiple threads can add to the cache, a few more values might be added.
3032
privateconstintNameCacheSizeSoftLimit=64;
@@ -325,35 +327,82 @@ internal override void WriteWithQuotes(Utf8JsonWriter writer, T value, JsonSeria
325327

326328
ulongkey=ConvertToUInt64(value);
327329

328-
if(_nameCache.TryGetValue(key,outJsonEncodedTextformatted))
330+
// Try to obtain values from caches
331+
if(options.DictionaryKeyPolicy!=null)
332+
{
333+
Debug.Assert(!state.Current.IgnoreDictionaryKeyPolicy);
334+
335+
if(_dictionaryKeyPolicyCache!=null&&_dictionaryKeyPolicyCache.TryGetValue(key,outJsonEncodedTextformatted))
336+
{
337+
writer.WritePropertyName(formatted);
338+
return;
339+
}
340+
}
341+
elseif(_nameCache.TryGetValue(key,outJsonEncodedTextformatted))
329342
{
330343
writer.WritePropertyName(formatted);
331344
return;
332345
}
333346

347+
348+
// if there are not cached values
334349
stringoriginal=value.ToString();
335350
if(IsValidIdentifier(original))
336351
{
337-
// We are dealing with a combination of flag constants since
338-
// all constant values were cached during warm-up.
339-
JavaScriptEncoder?encoder=options.Encoder;
340-
341-
if(_nameCache.Count<NameCacheSizeSoftLimit)
352+
if(options.DictionaryKeyPolicy!=null)
342353
{
343-
formatted=JsonEncodedText.Encode(original,encoder);
354+
original=options.DictionaryKeyPolicy.ConvertName(original);
344355

345-
writer.WritePropertyName(formatted);
356+
if(original==null)
357+
{
358+
ThrowHelper.ThrowInvalidOperationException_NamingPolicyReturnNull(options.DictionaryKeyPolicy);
359+
}
360+
361+
_dictionaryKeyPolicyCache??=newConcurrentDictionary<ulong,JsonEncodedText>();
362+
363+
if(_dictionaryKeyPolicyCache.Count<NameCacheSizeSoftLimit)
364+
{
365+
JavaScriptEncoder?encoder=options.Encoder;
366+
367+
JsonEncodedTextformatted=JsonEncodedText.Encode(original,encoder);
368+
369+
writer.WritePropertyName(formatted);
370+
371+
_dictionaryKeyPolicyCache.TryAdd(key,formatted);
372+
}
373+
else
374+
{
375+
// We also do not create a JsonEncodedText instance here because passing the string
376+
// directly to the writer is cheaper than creating one and not caching it for reuse.
377+
writer.WritePropertyName(original);
378+
}
346379

347-
_nameCache.TryAdd(key,formatted);
380+
return;
348381
}
349382
else
350383
{
351-
// We also do not create a JsonEncodedText instance here because passing the string
352-
// directly to the writer is cheaper than creating one and not caching it for reuse.
353-
writer.WritePropertyName(original);
354-
}
384+
// We might be dealing with a combination of flag constants since all constant values were
385+
// likely cached during warm - up(assuming the number of constants <= NameCacheSizeSoftLimit).
355386

356-
return;
387+
JavaScriptEncoder?encoder=options.Encoder;
388+
389+
if(_nameCache.Count<NameCacheSizeSoftLimit)
390+
{
391+
JsonEncodedTextformatted=JsonEncodedText.Encode(original,encoder);
392+
393+
writer.WritePropertyName(formatted);
394+
395+
_nameCache.TryAdd(key,formatted);
396+
}
397+
else
398+
{
399+
// We also do not create a JsonEncodedText instance here because passing the string
400+
// directly to the writer is cheaper than creating one and not caching it for reuse.
401+
writer.WritePropertyName(original);
402+
}
403+
404+
return;
405+
}
357406
}
358407

359408
switch(s_enumTypeCode)

‎src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.KeyPolicy.cs‎

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,101 @@ public async Task CustomNameSerialize()
188188
Assert.Equal(JsonCustomKey,json);
189189
}
190190

191+
publicenumETestEnum
192+
{
193+
TestValue1=1,
194+
TestValue2=2,
195+
}
196+
197+
[Fact]
198+
publicstaticvoidEnumSerialization_DictionaryPolicy_Honored_CamelCase()
199+
{
200+
varoptions=newJsonSerializerOptions
201+
{
202+
DictionaryKeyPolicy=JsonNamingPolicy.CamelCase,
203+
};
204+
205+
Dictionary<ETestEnum,ETestEnum>dict=newDictionary<ETestEnum,ETestEnum>{[ETestEnum.TestValue1]=ETestEnum.TestValue1};
206+
stringvalue=JsonSerializer.Serialize(dict,options);
207+
Assert.Equal("{\"testValue1\":1}",value);
208+
209+
dict=newDictionary<ETestEnum,ETestEnum>{[ETestEnum.TestValue2]=ETestEnum.TestValue2};
210+
value=JsonSerializer.Serialize(dict,options);
211+
Assert.Equal("{\"testValue2\":2}",value);
212+
213+
dict=newDictionary<ETestEnum,ETestEnum>{[ETestEnum.TestValue1]=ETestEnum.TestValue1,[ETestEnum.TestValue2]=ETestEnum.TestValue2};
214+
value=JsonSerializer.Serialize(dict,options);
215+
Assert.Equal("{\"testValue1\":1,\"testValue2\":2}",value);
216+
}
217+
218+
[Fact]
219+
publicstaticvoidEnumSerializationAsDictKey_NoDictionaryKeyPolicy()
220+
{
221+
Dictionary<ETestEnum,ETestEnum>dict=newDictionary<ETestEnum,ETestEnum>{[ETestEnum.TestValue1]=ETestEnum.TestValue1};
222+
stringvalue=JsonSerializer.Serialize(dict);
223+
Assert.Equal("{\"TestValue1\":1}",value);
224+
225+
dict=newDictionary<ETestEnum,ETestEnum>{[ETestEnum.TestValue2]=ETestEnum.TestValue2};
226+
value=JsonSerializer.Serialize(dict);
227+
Assert.Equal("{\"TestValue2\":2}",value);
228+
229+
dict=newDictionary<ETestEnum,ETestEnum>{[ETestEnum.TestValue1]=ETestEnum.TestValue1,[ETestEnum.TestValue2]=ETestEnum.TestValue2};
230+
value=JsonSerializer.Serialize(dict);
231+
Assert.Equal("{\"TestValue1\":1,\"TestValue2\":2}",value);
232+
}
233+
234+
publicclassClassWithEnumProperties
235+
{
236+
publicETestEnumTestEnumProperty1{get;}=ETestEnum.TestValue2;
237+
publicDayOfWeekTestEnumProperty2{get;}=DayOfWeek.Monday;
238+
}
239+
240+
[Fact]
241+
publicstaticvoidEnumSerialization_DictionaryPolicy_NotApplied_WhenEnumsAreSerialized()
242+
{
243+
varoptions=newJsonSerializerOptions
244+
{
245+
DictionaryKeyPolicy=JsonNamingPolicy.CamelCase,
246+
};
247+
248+
stringvalue=JsonSerializer.Serialize(DayOfWeek.Friday,options);
249+
250+
Assert.Equal("5",value);
251+
252+
value=JsonSerializer.Serialize(ETestEnum.TestValue2,options);
253+
254+
Assert.Equal("2",value);
255+
256+
257+
value=JsonSerializer.Serialize(newClassWithEnumProperties(),options);
258+
259+
Assert.Equal("{\"TestEnumProperty1\":2,\"TestEnumProperty2\":1}",value);
260+
261+
value=JsonSerializer.Serialize(newList<DayOfWeek>{DayOfWeek.Sunday,DayOfWeek.Monday,DayOfWeek.Tuesday,DayOfWeek.Wednesday,DayOfWeek.Thursday,DayOfWeek.Friday,DayOfWeek.Saturday},options);
262+
263+
Assert.Equal("[0,1,2,3,4,5,6]",value);
264+
}
265+
266+
publicclassCustomJsonNamingPolicy:JsonNamingPolicy
267+
{
268+
publicoverridestringConvertName(stringname)=>null;
269+
}
270+
271+
[Fact]
272+
publicstaticvoidEnumSerialization_DictionaryPolicy_ThrowsException_WhenNamingPolicyReturnsNull()
273+
{
274+
varoptions=newJsonSerializerOptions
275+
{
276+
DictionaryKeyPolicy=newCustomJsonNamingPolicy(),
277+
};
278+
279+
Dictionary<ETestEnum,ETestEnum>dict=newDictionary<ETestEnum,ETestEnum>{[ETestEnum.TestValue1]=ETestEnum.TestValue1};
280+
281+
InvalidOperationExceptionex=Assert.Throws<InvalidOperationException>(()=>JsonSerializer.Serialize(dict,options));
282+
283+
Assert.Contains(typeof(CustomJsonNamingPolicy).ToString(),ex.Message);
284+
}
285+
191286
[Fact]
192287
publicasyncTaskNullNamePolicy()
193288
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp