@@ -260,7 +260,19 @@ protected string TransformMethodCallExpression(MethodCallExpression e)
260
260
{
261
261
var fieldPath = TransformOperand ( l . Body ) ;
262
262
var propertyType = l . Body . Type ;
263
- var projection = GetJoinProjection ( fieldPath . Split ( new [ ] { '.' , '>' } ) . LastOrDefault ( ) , propertyType ) ;
263
+ var targetName = fieldPath . Split ( new [ ] { '.' , '>' } ) . LastOrDefault ( ) ;
264
+ var sourceName = targetName ;
265
+
266
+ // Arg 2: fieldName
267
+ if ( e . Arguments . Count > 2 && e . Arguments [ 2 ] is ConstantExpression c )
268
+ {
269
+ sourceName = c . Value ? . ToString ( ) ;
270
+ if ( string . IsNullOrEmpty ( sourceName ) )
271
+ {
272
+ sourceName = targetName ;
273
+ }
274
+ }
275
+ var projection = GetJoinProjection ( sourceName , targetName , propertyType ) ;
264
276
QueryBuilder . Includes [ fieldPath ] = projection ;
265
277
return projection ;
266
278
}
@@ -552,12 +564,15 @@ protected static List<string> GetPropertyProjectionList(Type type)
552
564
var isIgnored = prop . GetCustomAttributes ( typeof ( JsonIgnoreAttribute ) , true ) . Length > 0 ;
553
565
if ( ! isIgnored )
554
566
{
555
- var name = ( prop . GetCustomAttributes ( typeof ( JsonPropertyAttribute ) , true ) . FirstOrDefault ( ) as JsonPropertyAttribute ) ? . PropertyName ?? prop . Name . ToCamelCase ( ) ;
556
- var isIncluded = ( prop . GetCustomAttributes < IncludeAttribute > ( true ) . FirstOrDefault ( ) != null ) ;
567
+ var targetName = ( prop . GetCustomAttributes ( typeof ( JsonPropertyAttribute ) , true ) . FirstOrDefault ( ) as JsonPropertyAttribute ) ? . PropertyName ?? prop . Name . ToCamelCase ( ) ;
568
+ var includeAttr = prop . GetCustomAttributes < IncludeAttribute > ( true ) . FirstOrDefault ( ) ;
569
+ var sourceName = ! string . IsNullOrEmpty ( includeAttr ? . FieldName ) ? includeAttr . FieldName : targetName ;
570
+ var fieldRef = targetName == sourceName ? sourceName : $ "\" { targetName } \" : { sourceName } ";
571
+ bool isIncluded = includeAttr != null ;
557
572
if ( isIncluded )
558
573
{
559
574
// Add a join projection for [Include]d properties
560
- result . Add ( GetJoinProjection ( name , prop . PropertyType ) ) ;
575
+ result . Add ( GetJoinProjection ( sourceName , targetName , prop . PropertyType ) ) ;
561
576
}
562
577
else if ( prop . PropertyType . IsClass && prop . PropertyType != typeof ( string ) )
563
578
{
@@ -566,12 +581,16 @@ protected static List<string> GetPropertyProjectionList(Type type)
566
581
if ( isList )
567
582
{
568
583
// Array Case: Recursively add projection list for class types
569
- result . Add ( $ "{ name } []{{{GetPropertyProjectionList(listInterface.GetGenericArguments()[0]).Aggregate((c, n) => c + ", " + n)}}}" ) ;
584
+ var listItemProjection = GetPropertyProjectionList ( listInterface . GetGenericArguments ( ) [ 0 ] ) . Aggregate ( ( c , n ) => c + "," + n ) ;
585
+ if ( listItemProjection != "..." )
586
+ {
587
+ result . Add ( $ "{ fieldRef } []{{{listItemProjection}}}") ;
588
+ }
570
589
}
571
590
else
572
591
{
573
592
// Object Case: Recursively add projection list for class types
574
- result . Add ( $ "{ name } {{{GetPropertyProjectionList(prop.PropertyType).Aggregate((c, n) => c + ", " + n)}}}" ) ;
593
+ result . Add ( $ "{ fieldRef } {{{GetPropertyProjectionList(prop.PropertyType).Aggregate((c, n) => c + ", " + n)}}}" ) ;
575
594
}
576
595
}
577
596
}
@@ -583,17 +602,22 @@ protected static List<string> GetPropertyProjectionList(Type type)
583
602
/// Generates a projection for included / joined types using reflection.
584
603
/// Supports Lists and also nested objects of type SanityReference<> or IEnumerable<SanityReference>
585
604
/// </summary>
586
- /// <param name="fieldName "></param>
605
+ /// <param name="sourceName "></param>
587
606
/// <param name="propertyType"></param>
588
607
/// <returns></returns>
589
- public static string GetJoinProjection ( string fieldName , Type propertyType )
608
+ public static string GetJoinProjection ( string sourceName , string targetName , Type propertyType )
590
609
{
591
610
string projection = "" ;
611
+ var fieldRef = sourceName ;
612
+ if ( sourceName != targetName && ! string . IsNullOrEmpty ( targetName ) )
613
+ {
614
+ fieldRef = $ "\" { targetName } \" : { sourceName } ";
615
+ }
592
616
593
617
// String or primative
594
618
if ( propertyType == typeof ( string ) || propertyType . IsPrimitive )
595
619
{
596
- return fieldName ;
620
+ return fieldRef ;
597
621
}
598
622
599
623
var isSanityReferenceType = propertyType . IsGenericType && propertyType . GetGenericTypeDefinition ( ) == typeof ( SanityReference < > ) ;
@@ -602,7 +626,7 @@ public static string GetJoinProjection(string fieldName, Type propertyType)
602
626
// CASE 1: SanityReference<T>
603
627
var fields = GetPropertyProjectionList ( propertyType . GetGenericArguments ( ) [ 0 ] ) ;
604
628
var fieldList = fields . Aggregate ( ( c , n ) => c + "," + n ) ;
605
- projection = $ "{ fieldName } ->{{ { fieldList } }}";
629
+ projection = $ "{ fieldRef } ->{{ { fieldList } }}";
606
630
}
607
631
else
608
632
{
@@ -614,7 +638,7 @@ public static string GetJoinProjection(string fieldName, Type propertyType)
614
638
var elementType = listOfSanityReferenceType . GetGenericArguments ( ) [ 0 ] . GetGenericArguments ( ) [ 0 ] ;
615
639
var fields = GetPropertyProjectionList ( elementType ) ;
616
640
var fieldList = fields . Aggregate ( ( c , n ) => c + "," + n ) ;
617
- projection = $ "{ fieldName } []->{{ { fieldList } }}";
641
+ projection = $ "{ fieldRef } []->{{ { fieldList } }}";
618
642
}
619
643
else
620
644
{
@@ -630,7 +654,7 @@ public static string GetJoinProjection(string fieldName, Type propertyType)
630
654
631
655
// Nested Reference
632
656
var fieldList = fields . Select ( f => f . StartsWith ( "asset" ) ? $ "asset->{ ( nestedFields . Count > 0 ? ( "{" + nestedFields . Aggregate ( ( a , b ) => a + "," + b ) + "}" ) : "" ) } " : f ) . Aggregate ( ( c , n ) => c + "," + n ) ;
633
- projection = $ "{ fieldName } {{ { fieldList } }}";
657
+ projection = $ "{ fieldRef } {{ { fieldList } }}";
634
658
}
635
659
else
636
660
{
@@ -646,7 +670,7 @@ public static string GetJoinProjection(string fieldName, Type propertyType)
646
670
647
671
// Nested Reference
648
672
var fieldList = fields . Select ( f => f == propertyName ? $ "{ propertyName } ->{ ( nestedFields . Count > 0 ? ( "{" + nestedFields . Aggregate ( ( a , b ) => a + "," + b ) + "}" ) : "" ) } " : f ) . Aggregate ( ( c , n ) => c + "," + n ) ;
649
- projection = $ "{ fieldName } {{ { fieldList } }}";
673
+ projection = $ "{ fieldRef } {{ { fieldList } }}";
650
674
651
675
}
652
676
else
@@ -665,7 +689,7 @@ public static string GetJoinProjection(string fieldName, Type propertyType)
665
689
666
690
// Nested Reference
667
691
var fieldList = fields . Select ( f => f == propertyName ? $ "{ propertyName } []->{ ( nestedFields . Count > 0 ? ( "{" + nestedFields . Aggregate ( ( a , b ) => a + "," + b ) + "}" ) : "" ) } " : f ) . Aggregate ( ( c , n ) => c + "," + n ) ;
668
- projection = $ "{ fieldName } {{ { fieldList } }}";
692
+ projection = $ "{ fieldRef } {{ { fieldList } }}";
669
693
670
694
}
671
695
else
@@ -682,7 +706,7 @@ public static string GetJoinProjection(string fieldName, Type propertyType)
682
706
683
707
// Nested Reference
684
708
var fieldList = fields . Select ( f => f . StartsWith ( "asset" ) ? $ "asset->{{ ... }}" : f ) . Aggregate ( ( c , n ) => c + "," + n ) ;
685
- projection = $ "{ fieldName } [] {{ { fieldList } }}";
709
+ projection = $ "{ fieldRef } [] {{ { fieldList } }}";
686
710
}
687
711
}
688
712
}
@@ -703,12 +727,12 @@ public static string GetJoinProjection(string fieldName, Type propertyType)
703
727
{
704
728
// Other strongly typed includes
705
729
var fieldList = fields . Aggregate ( ( c , n ) => c + "," + n ) ;
706
- projection = $ "{ fieldName } []->{{ { fieldList } }}";
730
+ projection = $ "{ fieldRef } []->{{ { fieldList } }}";
707
731
}
708
732
else
709
733
{
710
734
// "object" without any fields defined
711
- projection = $ "{ fieldName } []->";
735
+ projection = $ "{ fieldRef } []->";
712
736
}
713
737
}
714
738
else
@@ -718,12 +742,12 @@ public static string GetJoinProjection(string fieldName, Type propertyType)
718
742
{
719
743
// Other strongly typed includes
720
744
var fieldList = fields . Aggregate ( ( c , n ) => c + "," + n ) ;
721
- projection = $ "{ fieldName } ->{{ { fieldList } }}";
745
+ projection = $ "{ fieldRef } ->{{ { fieldList } }}";
722
746
}
723
747
else
724
748
{
725
749
// "object" without any fields defined
726
- projection = $ "{ fieldName } ->{{ ... }}";
750
+ projection = $ "{ fieldRef } ->{{ ... }}";
727
751
}
728
752
}
729
753
}
@@ -791,10 +815,12 @@ public virtual string Build(bool includeProjections)
791
815
var includedProps = properties . Where ( p => p . GetCustomAttributes < IncludeAttribute > ( true ) . FirstOrDefault ( ) != null ) . ToList ( ) ;
792
816
foreach ( var prop in includedProps )
793
817
{
794
- var name = ( prop . GetCustomAttributes ( typeof ( JsonPropertyAttribute ) , true ) . FirstOrDefault ( ) as JsonPropertyAttribute ) ? . PropertyName ?? prop . Name . ToCamelCase ( ) ;
795
- if ( ! Includes . ContainsKey ( name ) )
818
+ var includeAttr = prop . GetCustomAttributes < IncludeAttribute > ( true ) . FirstOrDefault ( ) ;
819
+ var targetName = ( prop . GetCustomAttributes ( typeof ( JsonPropertyAttribute ) , true ) . FirstOrDefault ( ) as JsonPropertyAttribute ) ? . PropertyName ?? prop . Name . ToCamelCase ( ) ;
820
+ var sourceName = ! string . IsNullOrEmpty ( includeAttr . FieldName ) ? includeAttr . FieldName : targetName ;
821
+ if ( ! Includes . ContainsKey ( targetName ) )
796
822
{
797
- Includes . Add ( name , GetJoinProjection ( name , prop . PropertyType ) ) ;
823
+ Includes . Add ( targetName , GetJoinProjection ( sourceName , targetName , prop . PropertyType ) ) ;
798
824
}
799
825
}
800
826
}
@@ -878,6 +904,8 @@ private string ExpandIncludesInProjection(string projection, Dictionary<string,
878
904
var jObjectInclude = JsonConvert . DeserializeObject ( jsonInclude ) as JObject ;
879
905
880
906
var pathParts = includeKey
907
+ . Replace ( "\" :" , GroqTokens [ "\" :" ] )
908
+ . Replace ( "\" " , GroqTokens [ "\" " ] )
881
909
. Replace ( "[]" , GroqTokens [ "[]" ] )
882
910
. Replace ( "->" , "." )
883
911
. TrimEnd ( '.' ) . Split ( '.' ) ;
@@ -951,20 +979,23 @@ private string ExpandIncludesInProjection(string projection, Dictionary<string,
951
979
952
980
private Dictionary < string , string > GroqTokens = new Dictionary < string , string >
953
981
{
982
+ { "\" " , "VVV" } ,
983
+ { "\" :" , "WWW" } ,
954
984
{ "..." , "XXX" } ,
955
985
{ "->" , "YYY" } ,
956
- { "[]" , "ZZZ" }
957
-
986
+ { "[]" , "ZZZ" } ,
958
987
} ;
959
988
960
989
private string GroqToJson ( string groq )
961
990
{
962
991
var json = groq
963
992
. Replace ( " " , "" )
993
+ . Replace ( "\" :" , GroqTokens [ "\" :" ] )
994
+ . Replace ( "\" " , GroqTokens [ "\" " ] )
964
995
. Replace ( "{" , ":{" )
965
996
. Replace ( "..." , GroqTokens [ "..." ] )
966
997
. Replace ( "->" , GroqTokens [ "->" ] )
967
- . Replace ( "[]" , GroqTokens [ "[]" ] )
998
+ . Replace ( "[]" , GroqTokens [ "[]" ] )
968
999
. TrimStart ( ':' ) ;
969
1000
970
1001
// Replace variable names with valid json (e.g. convert myField to "myField":true)
@@ -993,7 +1024,9 @@ private string JsonToGroq(string json)
993
1024
. Replace ( ":{" , "{" )
994
1025
. Replace ( GroqTokens [ "[]" ] , "[]" )
995
1026
. Replace ( ":true" , "" )
996
- . Replace ( "\" " , "" ) ;
1027
+ . Replace ( "\" " , "" )
1028
+ . Replace ( GroqTokens [ "\" :" ] , "\" :" )
1029
+ . Replace ( GroqTokens [ "\" " ] , "\" " ) ;
997
1030
}
998
1031
}
999
1032
0 commit comments