1717using System . Reflection ;
1818using ServiceStack . Reflection ;
1919using ServiceStack . Text . Json ;
20+ using ServiceStack . Text . Jsv ;
2021
2122namespace ServiceStack . Text . Common
2223{
@@ -178,6 +179,7 @@ private static bool Init()
178179
179180 PropertyWriters [ i ] = new TypePropertyWriter
180181 (
182+ propertyType ,
181183 propertyName ,
182184 propertyDeclaredTypeName ,
183185 propertyNameCLSFriendly ,
@@ -234,6 +236,7 @@ private static bool Init()
234236
235237 PropertyWriters [ i + propertyNamesLength ] = new TypePropertyWriter
236238 (
239+ propertyType ,
237240 propertyName ,
238241 propertyDeclaredTypeName ,
239242 propertyNameCLSFriendly ,
@@ -267,6 +270,8 @@ internal string PropertyName
267270 : propertyName ;
268271 }
269272 }
273+
274+ internal readonly Type PropertyType ;
270275 internal readonly string propertyName ;
271276 internal readonly int propertyOrder ;
272277 internal readonly bool propertySuppressDefaultConfig ;
@@ -281,13 +286,14 @@ internal string PropertyName
281286 internal readonly Func < T , string , bool ? > shouldSerializeDynamic ;
282287 internal readonly bool isEnum ;
283288
284- public TypePropertyWriter ( string propertyName , string propertyDeclaredTypeName , string propertyNameCLSFriendly ,
289+ public TypePropertyWriter ( Type propertyType , string propertyName , string propertyDeclaredTypeName , string propertyNameCLSFriendly ,
285290 string propertyNameLowercaseUnderscore , int propertyOrder , bool propertySuppressDefaultConfig , bool propertySuppressDefaultAttribute ,
286291 Func < T , object > getterFn , WriteObjectDelegate writeFn , object defaultValue ,
287292 Func < T , bool > shouldSerialize ,
288293 Func < T , string , bool ? > shouldSerializeDynamic ,
289294 bool isEnum )
290295 {
296+ this . PropertyType = propertyType ;
291297 this . propertyName = propertyName ;
292298 this . propertyOrder = propertyOrder ;
293299 this . propertySuppressDefaultConfig = propertySuppressDefaultConfig ;
@@ -359,6 +365,15 @@ public static void WriteAbstractProperties(TextWriter writer, object value)
359365 WriteLateboundProperties ( writer , value , valueType ) ;
360366 }
361367
368+ internal static string GetPropertyName ( string propertyName )
369+ {
370+ return JsConfig < T > . EmitCamelCaseNames . GetValueOrDefault ( JsConfig . EmitCamelCaseNames )
371+ ? propertyName . ToCamelCase ( )
372+ : JsConfig < T > . EmitLowercaseUnderscoreNames . GetValueOrDefault ( JsConfig . EmitLowercaseUnderscoreNames )
373+ ? propertyName . ToLowercaseUnderscore ( )
374+ : propertyName ;
375+ }
376+
362377 public static void WriteProperties ( TextWriter writer , object value )
363378 {
364379 if ( value == null )
@@ -488,20 +503,54 @@ public static void WriteComplexQueryStringProperties(string typeName, TextWriter
488503 if ( i ++ > 0 )
489504 writer . Write ( '&' ) ;
490505
491- writer . Write ( typeName ) ;
492- writer . Write ( '[' ) ;
493- writer . Write ( propertyWriter . PropertyName ) ;
494- writer . Write ( ']' ) ;
506+ var propertyValueType = propertyValue != null ? propertyValue . GetType ( ) : null ;
507+ if ( propertyValueType != null &&
508+ propertyValueType . IsUserType ( ) &&
509+ ! propertyValueType . HasInterface ( typeof ( IEnumerable ) ) )
510+ {
511+ //Nested Complex Type: legal_entity[dob][day]=1
512+ var prefix = "{0}[{1}]" . Fmt ( typeName , propertyWriter . PropertyName ) ;
513+ var props = propertyValueType . GetSerializableProperties ( ) ;
514+ for ( int j = 0 ; j < props . Length ; j ++ )
515+ {
516+ var pi = props [ j ] ;
517+ var pValue = pi . GetValue ( propertyValue , new object [ 0 ] ) ;
518+ if ( pValue == null && ! Serializer . IncludeNullValues )
519+ continue ;
495520
496- writer . Write ( '=' ) ;
521+ if ( j > 0 )
522+ writer . Write ( '&' ) ;
497523
498- if ( propertyValue == null )
499- {
500- writer . Write ( JsonUtils . Null ) ;
524+ writer . Write ( prefix ) ;
525+ writer . Write ( '[' ) ;
526+ writer . Write ( GetPropertyName ( pi . Name ) ) ;
527+ writer . Write ( "]=" ) ;
528+
529+ if ( pValue == null )
530+ {
531+ writer . Write ( JsonUtils . Null ) ;
532+ }
533+ else
534+ {
535+ JsvWriter . GetWriteFn ( pValue . GetType ( ) ) ( writer , pValue ) ;
536+ }
537+ }
501538 }
502539 else
503540 {
504- propertyWriter . WriteFn ( writer , propertyValue ) ;
541+ writer . Write ( typeName ) ;
542+ writer . Write ( '[' ) ;
543+ writer . Write ( propertyWriter . PropertyName ) ;
544+ writer . Write ( "]=" ) ;
545+
546+ if ( propertyValue == null )
547+ {
548+ writer . Write ( JsonUtils . Null ) ;
549+ }
550+ else
551+ {
552+ propertyWriter . WriteFn ( writer , propertyValue ) ;
553+ }
505554 }
506555 }
507556 }
@@ -524,7 +573,7 @@ public static void WriteQueryString(TextWriter writer, object value)
524573 var propertyType = propertyValue . GetType ( ) ;
525574 var strValue = propertyValue as string ;
526575 var isEnumerable = strValue == null
527- && ! ( propertyType . IsValueType ( ) )
576+ && ! propertyType . IsValueType ( )
528577 && propertyType . HasInterface ( typeof ( IEnumerable ) ) ;
529578
530579 if ( QueryStringSerializer . ComplexTypeStrategy != null
0 commit comments