@@ -44,9 +44,9 @@ public override ResourceObject Read(ref Utf8JsonReader reader, Type typeToConver
4444
4545 var resourceObject = new ResourceObject
4646 {
47- // The 'attributes' element may occur before 'type', but we need to know the resource type before we can deserialize attributes
48- // into their corresponding CLR types.
49- Type = PeekType ( ref reader )
47+ // The 'attributes' or 'relationships' element may occur before 'type', but we need to know the resource type
48+ // before we can deserialize attributes/relationships into their corresponding CLR types.
49+ Type = PeekType ( reader )
5050 } ;
5151
5252 ResourceType ? resourceType = resourceObject . Type != null ? _resourceGraph . FindResourceType ( resourceObject . Type ) : null ;
@@ -99,7 +99,15 @@ public override ResourceObject Read(ref Utf8JsonReader reader, Type typeToConver
9999 }
100100 case "relationships" :
101101 {
102- resourceObject . Relationships = ReadRelationships ( ref reader , options ) ;
102+ if ( resourceType != null )
103+ {
104+ resourceObject . Relationships = ReadRelationships ( ref reader , options , resourceType ) ;
105+ }
106+ else
107+ {
108+ reader . Skip ( ) ;
109+ }
110+
103111 break ;
104112 }
105113 case "links" :
@@ -127,27 +135,27 @@ public override ResourceObject Read(ref Utf8JsonReader reader, Type typeToConver
127135 throw GetEndOfStreamError ( ) ;
128136 }
129137
130- private static string ? PeekType ( ref Utf8JsonReader reader )
138+ private static string ? PeekType ( Utf8JsonReader reader )
131139 {
132- // https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to?pivots=dotnet-5-0#an-alternative-way-to-do-polymorphic-deserialization
133- Utf8JsonReader readerClone = reader ;
140+ // This method receives a clone of the reader (which is a struct, and there's no ref modifier on the parameter),
141+ // so advancing here doesn't affect the reader position of the caller.
134142
135- while ( readerClone . Read ( ) )
143+ while ( reader . Read ( ) )
136144 {
137- if ( readerClone . TokenType == JsonTokenType . PropertyName )
145+ if ( reader . TokenType == JsonTokenType . PropertyName )
138146 {
139- string ? propertyName = readerClone . GetString ( ) ;
140- readerClone . Read ( ) ;
147+ string ? propertyName = reader . GetString ( ) ;
148+ reader . Read ( ) ;
141149
142150 switch ( propertyName )
143151 {
144152 case "type" :
145153 {
146- return readerClone . GetString ( ) ;
154+ return reader . GetString ( ) ;
147155 }
148156 default :
149157 {
150- readerClone . Skip ( ) ;
158+ reader . Skip ( ) ;
151159 break ;
152160 }
153161 }
@@ -181,7 +189,7 @@ public override ResourceObject Read(ref Utf8JsonReader reader, Type typeToConver
181189 string extensionNamespace = attributeName [ ..extensionSeparatorIndex ] ;
182190 string extensionName = attributeName [ ( extensionSeparatorIndex + 1 ) ..] ;
183191
184- ValidateExtensionInAttributes ( extensionNamespace , extensionName , reader ) ;
192+ ValidateExtensionInAttributes ( extensionNamespace , extensionName , resourceType , reader ) ;
185193 reader . Skip ( ) ;
186194 continue ;
187195 }
@@ -232,12 +240,14 @@ public override ResourceObject Read(ref Utf8JsonReader reader, Type typeToConver
232240 }
233241
234242 // Currently exposed for internal use only, so we don't need a breaking change when adding support for multiple extensions.
235- private protected virtual void ValidateExtensionInAttributes ( string extensionNamespace , string extensionName , Utf8JsonReader reader )
243+ // ReSharper disable once UnusedParameter.Global
244+ private protected virtual void ValidateExtensionInAttributes ( string extensionNamespace , string extensionName , ResourceType resourceType ,
245+ Utf8JsonReader reader )
236246 {
237247 throw new JsonException ( $ "Unsupported usage of JSON:API extension '{ extensionNamespace } ' in attributes.") ;
238248 }
239249
240- private Dictionary < string , RelationshipObject ? > ReadRelationships ( ref Utf8JsonReader reader , JsonSerializerOptions options )
250+ private Dictionary < string , RelationshipObject ? > ReadRelationships ( ref Utf8JsonReader reader , JsonSerializerOptions options , ResourceType resourceType )
241251 {
242252 var relationships = new Dictionary < string , RelationshipObject ? > ( ) ;
243253
@@ -261,7 +271,7 @@ private protected virtual void ValidateExtensionInAttributes(string extensionNam
261271 string extensionNamespace = relationshipName [ ..extensionSeparatorIndex ] ;
262272 string extensionName = relationshipName [ ( extensionSeparatorIndex + 1 ) ..] ;
263273
264- ValidateExtensionInRelationships ( extensionNamespace , extensionName , reader ) ;
274+ ValidateExtensionInRelationships ( extensionNamespace , extensionName , resourceType , reader ) ;
265275 reader . Skip ( ) ;
266276 continue ;
267277 }
@@ -277,7 +287,9 @@ private protected virtual void ValidateExtensionInAttributes(string extensionNam
277287 }
278288
279289 // Currently exposed for internal use only, so we don't need a breaking change when adding support for multiple extensions.
280- private protected virtual void ValidateExtensionInRelationships ( string extensionNamespace , string extensionName , Utf8JsonReader reader )
290+ // ReSharper disable once UnusedParameter.Global
291+ private protected virtual void ValidateExtensionInRelationships ( string extensionNamespace , string extensionName , ResourceType resourceType ,
292+ Utf8JsonReader reader )
281293 {
282294 throw new JsonException ( $ "Unsupported usage of JSON:API extension '{ extensionNamespace } ' in relationships.") ;
283295 }
0 commit comments