@@ -26,6 +26,43 @@ public static IDecoder<List<T>> CreateListDecoder<T>(IDecoder<T> itemDecoder)
2626 }
2727 }
2828
29+ /// <summary>
30+ /// Decoder for nullable struct.
31+ /// </summary>
32+ /// <typeparam name="T">Type of the struct.</typeparam>
33+ internal sealed class NullableDecoder < T > : IDecoder < T ? > where T : struct
34+ {
35+ /// <summary>
36+ /// The decoder.
37+ /// </summary>
38+ private readonly IDecoder < T > decoder ;
39+
40+ /// <summary>
41+ /// Initializes a new instance of the <see cref="NullableDecoder{T}"/>
42+ /// </summary>
43+ /// <param name="decoder">The decoder.</param>
44+ public NullableDecoder ( IDecoder < T > decoder )
45+ {
46+ this . decoder = decoder ;
47+ }
48+
49+ /// <summary>
50+ /// The decode.
51+ /// </summary>
52+ /// <param name="reader">The reader.</param>
53+ /// <returns>The value.</returns>
54+ public T ? Decode ( IJsonReader reader )
55+ {
56+ if ( reader . IsNull )
57+ {
58+ reader . Read ( ) ;
59+ return null ;
60+ }
61+
62+ return this . decoder . Decode ( reader ) ;
63+ }
64+ }
65+
2966 /// <summary>
3067 /// Decoder for Int32.
3168 /// </summary>
@@ -36,6 +73,11 @@ internal sealed class Int32Decoder : IDecoder<int>
3673 /// </summary>
3774 public static readonly IDecoder < int > Instance = new Int32Decoder ( ) ;
3875
76+ /// <summary>
77+ /// The instance for nullable.
78+ /// </summary>
79+ public static readonly IDecoder < int ? > NullableInstance = new NullableDecoder < int > ( Instance ) ;
80+
3981 /// <summary>
4082 /// The decode.
4183 /// </summary>
@@ -57,6 +99,11 @@ internal sealed class Int64Decoder : IDecoder<long>
5799 /// </summary>
58100 public static readonly IDecoder < long > Instance = new Int64Decoder ( ) ;
59101
102+ /// <summary>
103+ /// The instance for nullable.
104+ /// </summary>
105+ public static readonly IDecoder < long ? > NullableInstance = new NullableDecoder < long > ( Instance ) ;
106+
60107 /// <summary>
61108 /// The decode.
62109 /// </summary>
@@ -78,6 +125,11 @@ internal sealed class UInt32Decoder : IDecoder<uint>
78125 /// </summary>
79126 public static readonly IDecoder < uint > Instance = new UInt32Decoder ( ) ;
80127
128+ /// <summary>
129+ /// The instance for nullable.
130+ /// </summary>
131+ public static readonly IDecoder < uint ? > NullableInstance = new NullableDecoder < uint > ( Instance ) ;
132+
81133 /// <summary>
82134 /// The decode.
83135 /// </summary>
@@ -99,6 +151,11 @@ internal sealed class UInt64Decoder : IDecoder<ulong>
99151 /// </summary>
100152 public static readonly IDecoder < ulong > Instance = new UInt64Decoder ( ) ;
101153
154+ /// <summary>
155+ /// The instance for nullable.
156+ /// </summary>
157+ public static readonly IDecoder < ulong ? > NullableInstance = new NullableDecoder < ulong > ( Instance ) ;
158+
102159 /// <summary>
103160 /// The decode.
104161 /// </summary>
@@ -120,6 +177,11 @@ internal sealed class SingleDecoder : IDecoder<float>
120177 /// </summary>
121178 public static readonly IDecoder < float > Instance = new SingleDecoder ( ) ;
122179
180+ /// <summary>
181+ /// The instance for nullable.
182+ /// </summary>
183+ public static readonly IDecoder < float ? > NullableInstance = new NullableDecoder < float > ( Instance ) ;
184+
123185 /// <summary>
124186 /// The decode.
125187 /// </summary>
@@ -141,6 +203,11 @@ internal sealed class DoubleDecoder : IDecoder<double>
141203 /// </summary>
142204 public static readonly IDecoder < double > Instance = new DoubleDecoder ( ) ;
143205
206+ /// <summary>
207+ /// The instance for nullable.
208+ /// </summary>
209+ public static readonly IDecoder < double ? > NullableInstance = new NullableDecoder < double > ( Instance ) ;
210+
144211 /// <summary>
145212 /// The decode.
146213 /// </summary>
@@ -162,6 +229,11 @@ internal sealed class BooleanDecoder : IDecoder<bool>
162229 /// </summary>
163230 public static readonly IDecoder < bool > Instance = new BooleanDecoder ( ) ;
164231
232+ /// <summary>
233+ /// The instance for nullable.
234+ /// </summary>
235+ public static readonly IDecoder < bool ? > NullableInstance = new NullableDecoder < bool > ( Instance ) ;
236+
165237 /// <summary>
166238 /// The decode.
167239 /// </summary>
@@ -183,6 +255,11 @@ internal sealed class DateTimeDecoder : IDecoder<DateTime>
183255 /// </summary>
184256 public static readonly IDecoder < DateTime > Instance = new DateTimeDecoder ( ) ;
185257
258+ /// <summary>
259+ /// The instance for nullable.
260+ /// </summary>
261+ public static readonly IDecoder < DateTime ? > NullableInstance = new NullableDecoder < DateTime > ( Instance ) ;
262+
186263 /// <summary>
187264 /// The decode.
188265 /// </summary>
@@ -240,7 +317,7 @@ public string Decode(IJsonReader reader)
240317 /// Decoder for struct type.
241318 /// </summary>
242319 /// <typeparam name="T">The struct type.</typeparam>
243- internal abstract class StructDecoder < T > : IDecoder < T >
320+ internal abstract class StructDecoder < T > : IDecoder < T > where T : class
244321 {
245322 /// <summary>
246323 /// The decode.
@@ -249,6 +326,12 @@ internal abstract class StructDecoder<T> : IDecoder<T>
249326 /// <returns>The value.</returns>
250327 public T Decode ( IJsonReader reader )
251328 {
329+ if ( reader . IsNull )
330+ {
331+ reader . Read ( ) ;
332+ return null ;
333+ }
334+
252335 EnsureStartObject ( reader ) ;
253336
254337 var obj = this . DecodeFields ( reader ) ;
@@ -357,7 +440,7 @@ private static void EnsureEndObject(IJsonReader reader)
357440 /// Decoder for union type.
358441 /// </summary>
359442 /// <typeparam name="T">The union type.</typeparam>
360- internal abstract class UnionDecoder < T > : StructDecoder < T > where T : new ( )
443+ internal abstract class UnionDecoder < T > : StructDecoder < T > where T : class , new ( )
361444 {
362445 /// <summary>
363446 /// Decode fields without ensuring start and end object.
0 commit comments