33
44using System ;
55using System . Buffers ;
6+ using System . Collections . Generic ;
67using System . IO ;
78using System . Linq ;
89using System . Text ;
@@ -51,7 +52,7 @@ public void Constructor_UsesSerializerSettings()
5152public async Task ChangesTo_SerializerSettings_AffectSerialization ( )
5253{
5354// Arrange
54- var person = new User ( ) { Name = "John" , Age = 35 } ;
55+ var person = new User ( ) { FullName = "John" , age = 35 } ;
5556var outputFormatterContext = GetOutputFormatterContext ( person , typeof ( User ) ) ;
5657
5758var settings = new JsonSerializerSettings
@@ -79,7 +80,7 @@ public async Task ChangesTo_SerializerSettings_AffectSerialization()
7980public async Task ChangesTo_SerializerSettings_AfterSerialization_DoNotAffectSerialization ( )
8081{
8182// Arrange
82- var person = new User ( ) { Name = "John" , Age = 35 } ;
83+ var person = new User ( ) { FullName = "John" , age = 35 } ;
8384var expectedOutput = JsonConvert . SerializeObject ( person , new JsonSerializerSettings ( ) ) ;
8485
8586var jsonFormatter = new TestableJsonOutputFormatter ( new JsonSerializerSettings ( ) ) ;
@@ -107,6 +108,172 @@ public async Task ChangesTo_SerializerSettings_AfterSerialization_DoNotAffectSer
107108Assert . Equal ( expectedOutput , content ) ;
108109}
109110
111+ public static TheoryData < NamingStrategy , string > NamingStrategy_AffectsSerializationData
112+ {
113+ get
114+ {
115+ return new TheoryData < NamingStrategy , string >
116+ {
117+ { new CamelCaseNamingStrategy ( ) , "{\" fullName\" :\" John\" ,\" age\" :35}" } ,
118+ { new DefaultNamingStrategy ( ) , "{\" FullName\" :\" John\" ,\" age\" :35}" } ,
119+ { new SnakeCaseNamingStrategy ( ) , "{\" full_name\" :\" John\" ,\" age\" :35}" } ,
120+ } ;
121+ }
122+ }
123+
124+ [ Theory ]
125+ [ MemberData ( nameof ( NamingStrategy_AffectsSerializationData ) ) ]
126+ public async Task NamingStrategy_AffectsSerialization ( NamingStrategy strategy , string expected )
127+ {
128+ // Arrange
129+ var user = new User { FullName = "John" , age = 35 } ;
130+ var context = GetOutputFormatterContext ( user , typeof ( User ) ) ;
131+
132+ var settings = new JsonSerializerSettings
133+ {
134+ ContractResolver = new DefaultContractResolver
135+ {
136+ NamingStrategy = strategy ,
137+ } ,
138+ } ;
139+ var formatter = new TestableJsonOutputFormatter ( settings ) ;
140+
141+ // Act
142+ await formatter . WriteResponseBodyAsync ( context , Encoding . UTF8 ) ;
143+
144+ // Assert
145+ var body = context . HttpContext . Response . Body ;
146+
147+ Assert . NotNull ( body ) ;
148+ body . Position = 0 ;
149+
150+ var content = new StreamReader ( body , Encoding . UTF8 ) . ReadToEnd ( ) ;
151+ Assert . Equal ( expected , content ) ;
152+ }
153+
154+ public static TheoryData < NamingStrategy > NamingStrategy_DoesNotAffectSerializationData
155+ {
156+ get
157+ {
158+ return new TheoryData < NamingStrategy >
159+ {
160+ { new CamelCaseNamingStrategy ( ) } ,
161+ { new DefaultNamingStrategy ( ) } ,
162+ { new SnakeCaseNamingStrategy ( ) } ,
163+ } ;
164+ }
165+ }
166+
167+ [ Theory ]
168+ [ MemberData ( nameof ( NamingStrategy_DoesNotAffectSerializationData ) ) ]
169+ public async Task NamingStrategy_DoesNotAffectDictionarySerialization ( NamingStrategy strategy )
170+ {
171+ // Arrange
172+ var dictionary = new Dictionary < string , int > ( StringComparer . Ordinal )
173+ {
174+ { "id" , 12 } ,
175+ { "Id" , 12 } ,
176+ { "fullName" , 12 } ,
177+ { "full-name" , 12 } ,
178+ { "FullName" , 12 } ,
179+ { "full_Name" , 12 } ,
180+ } ;
181+ var expected = "{\" id\" :12,\" Id\" :12,\" fullName\" :12,\" full-name\" :12,\" FullName\" :12,\" full_Name\" :12}" ;
182+ var context = GetOutputFormatterContext ( dictionary , typeof ( Dictionary < string , int > ) ) ;
183+
184+ var settings = new JsonSerializerSettings
185+ {
186+ ContractResolver = new DefaultContractResolver
187+ {
188+ NamingStrategy = strategy ,
189+ } ,
190+ } ;
191+ var formatter = new TestableJsonOutputFormatter ( settings ) ;
192+
193+ // Act
194+ await formatter . WriteResponseBodyAsync ( context , Encoding . UTF8 ) ;
195+
196+ // Assert
197+ var body = context . HttpContext . Response . Body ;
198+
199+ Assert . NotNull ( body ) ;
200+ body . Position = 0 ;
201+
202+ var content = new StreamReader ( body , Encoding . UTF8 ) . ReadToEnd ( ) ;
203+ Assert . Equal ( expected , content ) ;
204+ }
205+
206+ [ Theory ]
207+ [ MemberData ( nameof ( NamingStrategy_DoesNotAffectSerializationData ) ) ]
208+ public async Task NamingStrategy_DoesNotAffectSerialization_WithJsonProperty ( NamingStrategy strategy )
209+ {
210+ // Arrange
211+ var user = new UserWithJsonProperty
212+ {
213+ Name = "Joe" ,
214+ AnotherName = "Joe" ,
215+ ThirdName = "Joe" ,
216+ } ;
217+ var expected = "{\" ThisIsTheFullName\" :\" Joe\" ,\" another_name\" :\" Joe\" ,\" ThisIsTheThirdName\" :\" Joe\" }" ;
218+ var context = GetOutputFormatterContext ( user , typeof ( UserWithJsonProperty ) ) ;
219+
220+ var settings = new JsonSerializerSettings
221+ {
222+ ContractResolver = new DefaultContractResolver
223+ {
224+ NamingStrategy = strategy ,
225+ } ,
226+ } ;
227+ var formatter = new TestableJsonOutputFormatter ( settings ) ;
228+
229+ // Act
230+ await formatter . WriteResponseBodyAsync ( context , Encoding . UTF8 ) ;
231+
232+ // Assert
233+ var body = context . HttpContext . Response . Body ;
234+
235+ Assert . NotNull ( body ) ;
236+ body . Position = 0 ;
237+
238+ var content = new StreamReader ( body , Encoding . UTF8 ) . ReadToEnd ( ) ;
239+ Assert . Equal ( expected , content ) ;
240+ }
241+
242+ [ Theory ]
243+ [ MemberData ( nameof ( NamingStrategy_DoesNotAffectSerializationData ) ) ]
244+ public async Task NamingStrategy_DoesNotAffectSerialization_WithJsonObject ( NamingStrategy strategy )
245+ {
246+ // Arrange
247+ var user = new UserWithJsonObject
248+ {
249+ age = 35 ,
250+ FullName = "John" ,
251+ } ;
252+ var expected = "{\" age\" :35,\" full_name\" :\" John\" }" ;
253+ var context = GetOutputFormatterContext ( user , typeof ( UserWithJsonProperty ) ) ;
254+
255+ var settings = new JsonSerializerSettings
256+ {
257+ ContractResolver = new DefaultContractResolver
258+ {
259+ NamingStrategy = strategy ,
260+ } ,
261+ } ;
262+ var formatter = new TestableJsonOutputFormatter ( settings ) ;
263+
264+ // Act
265+ await formatter . WriteResponseBodyAsync ( context , Encoding . UTF8 ) ;
266+
267+ // Assert
268+ var body = context . HttpContext . Response . Body ;
269+
270+ Assert . NotNull ( body ) ;
271+ body . Position = 0 ;
272+
273+ var content = new StreamReader ( body , Encoding . UTF8 ) . ReadToEnd ( ) ;
274+ Assert . Equal ( expected , content ) ;
275+ }
276+
110277[ Fact ]
111278public async Task WriteToStreamAsync_RoundTripsJToken ( )
112279{
@@ -269,9 +436,30 @@ public TestableJsonOutputFormatter(JsonSerializerSettings serializerSettings)
269436
270437private sealed class User
271438{
439+ public string FullName { get ; set ; }
440+
441+ public int age { get ; set ; }
442+ }
443+
444+ private class UserWithJsonProperty
445+ {
446+ [ JsonProperty ( "ThisIsTheFullName" ) ]
272447public string Name { get ; set ; }
273448
274- public int Age { get ; set ; }
449+ [ JsonProperty ( NamingStrategyType = typeof ( SnakeCaseNamingStrategy ) ) ]
450+ public string AnotherName { get ; set ; }
451+
452+ // NamingStrategyType should be ignored with an explicit name.
453+ [ JsonProperty ( "ThisIsTheThirdName" , NamingStrategyType = typeof ( SnakeCaseNamingStrategy ) ) ]
454+ public string ThirdName { get ; set ; }
455+ }
456+
457+ [ JsonObject ( NamingStrategyType = typeof ( SnakeCaseNamingStrategy ) ) ]
458+ private class UserWithJsonObject
459+ {
460+ public int age { get ; set ; }
461+
462+ public string FullName { get ; set ; }
275463}
276464}
277465}