Skip to content

Commit

Permalink
Merge pull request #1689 from json-api-dotnet/merge-master-into-openapi
Browse files Browse the repository at this point in the history
Merge master into openapi
  • Loading branch information
bkoelman authored Feb 23, 2025
2 parents 4635800 + dbde12d commit 6d33a9a
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ public override ResourceObject Read(ref Utf8JsonReader reader, Type typeToConver

var resourceObject = new ResourceObject
{
// The 'attributes' element may occur before 'type', but we need to know the resource type before we can deserialize attributes
// into their corresponding CLR types.
Type = PeekType(ref reader)
// The 'attributes' or 'relationships' element may occur before 'type', but we need to know the resource type
// before we can deserialize attributes/relationships into their corresponding CLR types.
Type = PeekType(reader)
};

ResourceType? resourceType = resourceObject.Type != null ? _resourceGraph.FindResourceType(resourceObject.Type) : null;
Expand Down Expand Up @@ -99,7 +99,15 @@ public override ResourceObject Read(ref Utf8JsonReader reader, Type typeToConver
}
case "relationships":
{
resourceObject.Relationships = ReadRelationships(ref reader, options);
if (resourceType != null)
{
resourceObject.Relationships = ReadRelationships(ref reader, options, resourceType);
}
else
{
reader.Skip();
}

break;
}
case "links":
Expand Down Expand Up @@ -127,27 +135,27 @@ public override ResourceObject Read(ref Utf8JsonReader reader, Type typeToConver
throw GetEndOfStreamError();
}

private static string? PeekType(ref Utf8JsonReader reader)
private static string? PeekType(Utf8JsonReader reader)
{
// 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
Utf8JsonReader readerClone = reader;
// This method receives a clone of the reader (which is a struct, and there's no ref modifier on the parameter),
// so advancing here doesn't affect the reader position of the caller.

while (readerClone.Read())
while (reader.Read())
{
if (readerClone.TokenType == JsonTokenType.PropertyName)
if (reader.TokenType == JsonTokenType.PropertyName)
{
string? propertyName = readerClone.GetString();
readerClone.Read();
string? propertyName = reader.GetString();
reader.Read();

switch (propertyName)
{
case "type":
{
return readerClone.GetString();
return reader.GetString();
}
default:
{
readerClone.Skip();
reader.Skip();
break;
}
}
Expand Down Expand Up @@ -181,7 +189,7 @@ public override ResourceObject Read(ref Utf8JsonReader reader, Type typeToConver
string extensionNamespace = attributeName[..extensionSeparatorIndex];
string extensionName = attributeName[(extensionSeparatorIndex + 1)..];

ValidateExtensionInAttributes(extensionNamespace, extensionName, reader);
ValidateExtensionInAttributes(extensionNamespace, extensionName, resourceType, reader);
reader.Skip();
continue;
}
Expand Down Expand Up @@ -232,12 +240,14 @@ public override ResourceObject Read(ref Utf8JsonReader reader, Type typeToConver
}

// Currently exposed for internal use only, so we don't need a breaking change when adding support for multiple extensions.
private protected virtual void ValidateExtensionInAttributes(string extensionNamespace, string extensionName, Utf8JsonReader reader)
// ReSharper disable once UnusedParameter.Global
private protected virtual void ValidateExtensionInAttributes(string extensionNamespace, string extensionName, ResourceType resourceType,
Utf8JsonReader reader)
{
throw new JsonException($"Unsupported usage of JSON:API extension '{extensionNamespace}' in attributes.");
}

private Dictionary<string, RelationshipObject?> ReadRelationships(ref Utf8JsonReader reader, JsonSerializerOptions options)
private Dictionary<string, RelationshipObject?> ReadRelationships(ref Utf8JsonReader reader, JsonSerializerOptions options, ResourceType resourceType)
{
var relationships = new Dictionary<string, RelationshipObject?>();

Expand All @@ -261,7 +271,7 @@ private protected virtual void ValidateExtensionInAttributes(string extensionNam
string extensionNamespace = relationshipName[..extensionSeparatorIndex];
string extensionName = relationshipName[(extensionSeparatorIndex + 1)..];

ValidateExtensionInRelationships(extensionNamespace, extensionName, reader);
ValidateExtensionInRelationships(extensionNamespace, extensionName, resourceType, reader);
reader.Skip();
continue;
}
Expand All @@ -277,7 +287,9 @@ private protected virtual void ValidateExtensionInAttributes(string extensionNam
}

// Currently exposed for internal use only, so we don't need a breaking change when adding support for multiple extensions.
private protected virtual void ValidateExtensionInRelationships(string extensionNamespace, string extensionName, Utf8JsonReader reader)
// ReSharper disable once UnusedParameter.Global
private protected virtual void ValidateExtensionInRelationships(string extensionNamespace, string extensionName, ResourceType resourceType,
Utf8JsonReader reader)
{
throw new JsonException($"Unsupported usage of JSON:API extension '{extensionNamespace}' in relationships.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,8 @@ public ExtensionAwareResourceObjectConverter(IResourceGraph resourceGraph, JsonA
_requestAccessor = requestAccessor;
}

private protected override void ValidateExtensionInAttributes(string extensionNamespace, string extensionName, Utf8JsonReader reader)
private protected override void ValidateExtensionInAttributes(string extensionNamespace, string extensionName, ResourceType resourceType,
Utf8JsonReader reader)
{
if (extensionNamespace == ExtensionNamespace && IsTypeInfoExtensionEnabled && extensionName == "fail")
{
Expand All @@ -429,10 +430,11 @@ private protected override void ValidateExtensionInAttributes(string extensionNa
return;
}

base.ValidateExtensionInAttributes(extensionNamespace, extensionName, reader);
base.ValidateExtensionInAttributes(extensionNamespace, extensionName, resourceType, reader);
}

private protected override void ValidateExtensionInRelationships(string extensionNamespace, string extensionName, Utf8JsonReader reader)
private protected override void ValidateExtensionInRelationships(string extensionNamespace, string extensionName, ResourceType resourceType,
Utf8JsonReader reader)
{
if (extensionNamespace == ExtensionNamespace && IsTypeInfoExtensionEnabled && extensionName == "fail")
{
Expand All @@ -444,7 +446,7 @@ private protected override void ValidateExtensionInRelationships(string extensio
return;
}

base.ValidateExtensionInRelationships(extensionNamespace, extensionName, reader);
base.ValidateExtensionInRelationships(extensionNamespace, extensionName, resourceType, reader);
}

private protected override void WriteExtensionInAttributes(Utf8JsonWriter writer, ResourceObject value)
Expand Down

0 comments on commit 6d33a9a

Please sign in to comment.