@@ -964,5 +964,142 @@ private class ClassWithExplicitOrderOfProperties
964
964
[ JsonPropertyOrder ( - 2 ) ]
965
965
public string A { get ; set ; }
966
966
}
967
+
968
+ [ Fact ]
969
+ public static void RecursiveTypeWithResolverResolvingOnlyThatType ( )
970
+ {
971
+ TestResolver resolver = new ( ResolveTypeInfo ) ;
972
+
973
+ JsonSerializerOptions options = new ( ) ;
974
+ options . TypeInfoResolver = resolver ;
975
+
976
+ string json = JsonSerializer . Serialize ( new RecursiveType ( ) { Next = new RecursiveType ( ) } , options ) ;
977
+ Assert . Equal ( """{"Next":{"Next":null}}""" , json ) ;
978
+
979
+ RecursiveType deserialized = JsonSerializer . Deserialize < RecursiveType > ( json , options ) ;
980
+ Assert . NotNull ( deserialized ) ;
981
+ Assert . Equal ( 2 , deserialized . Value ) ;
982
+ Assert . NotNull ( deserialized . Next ) ;
983
+ Assert . Equal ( 1 , deserialized . Next . Value ) ;
984
+ Assert . Null ( deserialized . Next . Next ) ;
985
+
986
+ static JsonTypeInfo ? ResolveTypeInfo ( Type type , JsonSerializerOptions options )
987
+ {
988
+ int value = 1 ;
989
+ if ( type == typeof ( RecursiveType ) )
990
+ {
991
+ JsonTypeInfo < RecursiveType > ti = JsonTypeInfo . CreateJsonTypeInfo < RecursiveType > ( options ) ;
992
+ ti . CreateObject = ( ) => new RecursiveType ( ) ;
993
+ JsonPropertyInfo prop = ti . CreateJsonPropertyInfo ( typeof ( RecursiveType ) , "Next" ) ;
994
+ prop . Get = ( obj ) => ( ( RecursiveType ) obj ) . Next ;
995
+ prop . Set = ( obj , val ) =>
996
+ {
997
+ RecursiveType recursiveObj = ( RecursiveType ) obj ;
998
+ recursiveObj . Next = ( RecursiveType ) val ;
999
+ recursiveObj . Value = value ++ ;
1000
+ } ;
1001
+ ti . Properties . Add ( prop ) ;
1002
+ return ti ;
1003
+ }
1004
+
1005
+ return null ;
1006
+ }
1007
+ }
1008
+
1009
+ [ Fact ]
1010
+ public static void RecursiveTypeWithResolverResolvingOnlyThatTypeThrowsWhenPropertyOfDifferentType ( )
1011
+ {
1012
+ TestResolver resolver = new ( ResolveTypeInfo ) ;
1013
+
1014
+ JsonSerializerOptions options = new ( ) ;
1015
+ options . TypeInfoResolver = resolver ;
1016
+
1017
+ Assert . Throws < NotSupportedException > ( ( ) => JsonSerializer . Serialize ( new RecursiveType ( ) { Next = new RecursiveType ( ) } , options ) ) ;
1018
+ Assert . Throws < NotSupportedException > ( ( ) => JsonSerializer . Deserialize < RecursiveType > ( """{"Next":{"Next":null}}""" , options ) ) ;
1019
+
1020
+ static JsonTypeInfo ? ResolveTypeInfo ( Type type , JsonSerializerOptions options )
1021
+ {
1022
+ if ( type == typeof ( RecursiveType ) )
1023
+ {
1024
+ JsonTypeInfo < RecursiveType > ti = JsonTypeInfo . CreateJsonTypeInfo < RecursiveType > ( options ) ;
1025
+ ti . CreateObject = ( ) => new RecursiveType ( ) ;
1026
+ {
1027
+ JsonPropertyInfo prop = ti . CreateJsonPropertyInfo ( typeof ( RecursiveType ) , "Next" ) ;
1028
+ prop . Get = ( obj ) => ( ( RecursiveType ) obj ) . Next ;
1029
+ prop . Set = ( obj , val ) => ( ( RecursiveType ) obj ) . Next = ( RecursiveType ) val ;
1030
+ ti . Properties . Add ( prop ) ;
1031
+ }
1032
+ {
1033
+ JsonPropertyInfo prop = ti . CreateJsonPropertyInfo ( typeof ( int ) , "Value" ) ;
1034
+ prop . Get = ( obj ) => ( ( RecursiveType ) obj ) . Value ;
1035
+ prop . Set = ( obj , val ) => ( ( RecursiveType ) obj ) . Value = ( int ) val ;
1036
+ ti . Properties . Add ( prop ) ;
1037
+ }
1038
+
1039
+ return ti ;
1040
+ }
1041
+
1042
+ return null ;
1043
+ }
1044
+ }
1045
+
1046
+ [ Fact ]
1047
+ public static void RecursiveTypeWithResolverResolvingOnlyUsedTypes ( )
1048
+ {
1049
+ TestResolver resolver = new ( ResolveTypeInfo ) ;
1050
+
1051
+ JsonSerializerOptions options = new ( ) ;
1052
+ options . TypeInfoResolver = resolver ;
1053
+
1054
+ RecursiveType obj = new RecursiveType ( )
1055
+ {
1056
+ Value = 13 ,
1057
+ Next = new RecursiveType ( ) { Value = 7 } ,
1058
+ } ;
1059
+ string json = JsonSerializer . Serialize ( obj , options ) ;
1060
+ Assert . Equal ( """{"Next":{"Next":null,"Value":7},"Value":13}""" , json ) ;
1061
+
1062
+ RecursiveType deserialized = JsonSerializer . Deserialize < RecursiveType > ( json , options ) ;
1063
+ Assert . NotNull ( deserialized ) ;
1064
+ Assert . Equal ( 13 , deserialized . Value ) ;
1065
+ Assert . NotNull ( deserialized . Next ) ;
1066
+ Assert . Equal ( 7 , deserialized . Next . Value ) ;
1067
+ Assert . Null ( deserialized . Next . Next ) ;
1068
+
1069
+ static JsonTypeInfo ? ResolveTypeInfo ( Type type , JsonSerializerOptions options )
1070
+ {
1071
+ if ( type == typeof ( RecursiveType ) )
1072
+ {
1073
+ JsonTypeInfo < RecursiveType > ti = JsonTypeInfo . CreateJsonTypeInfo < RecursiveType > ( options ) ;
1074
+ ti . CreateObject = ( ) => new RecursiveType ( ) ;
1075
+ {
1076
+ JsonPropertyInfo prop = ti . CreateJsonPropertyInfo ( typeof ( RecursiveType ) , "Next" ) ;
1077
+ prop . Get = ( obj ) => ( ( RecursiveType ) obj ) . Next ;
1078
+ prop . Set = ( obj , val ) => ( ( RecursiveType ) obj ) . Next = ( RecursiveType ) val ;
1079
+ ti . Properties . Add ( prop ) ;
1080
+ }
1081
+ {
1082
+ JsonPropertyInfo prop = ti . CreateJsonPropertyInfo ( typeof ( int ) , "Value" ) ;
1083
+ prop . Get = ( obj ) => ( ( RecursiveType ) obj ) . Value ;
1084
+ prop . Set = ( obj , val ) => ( ( RecursiveType ) obj ) . Value = ( int ) val ;
1085
+ ti . Properties . Add ( prop ) ;
1086
+ }
1087
+ return ti ;
1088
+ }
1089
+
1090
+ if ( type == typeof ( int ) )
1091
+ {
1092
+ return JsonTypeInfo . CreateJsonTypeInfo < int > ( options ) ;
1093
+ }
1094
+
1095
+ return null ;
1096
+ }
1097
+ }
1098
+
1099
+ private class RecursiveType
1100
+ {
1101
+ public int Value { get ; set ; }
1102
+ public RecursiveType ? Next { get ; set ; }
1103
+ }
967
1104
}
968
1105
}
0 commit comments