ChilliCream / ChilliCream/graphql-platform
Bug when deserializing multiple custom scalars to same type
Nobody has claimed this yet.
- Dominant language
- C#
- Stars
- 5.8k
- Forks
- 810
- Avg merge
- 15h 39m
- Merged PRs (30d)
- 98
Description
Is there an existing issue for this?
- I have searched the existing issues
Product
Strawberry Shake
Describe the bug
When multiple custom scalar deserializers are defined that deserialize to the same type, the Deserialize methods in the generated code will overlap and one of the custom deserializers will be used for both types.
Example query:
query TestMultipleScalar {
a
b
}
type Query { a: A, b: B }
scalar A
scalar B
extend scalar A
@serializationType(name: "global::System.Text.Json.JsonElement")
@runtimeType(name: "global::System.String")
extend scalar B
@serializationType(name: "global::System.Text.Json.JsonElement")
@runtimeType(name: "global::System.String")
Generated code:
[global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
public partial class TestMultipleScalarBuilder : global::StrawberryShake.OperationResultBuilder<global::Foo.Bar.ITestMultipleScalarResult>
{
private readonly global::StrawberryShake.IEntityStore _entityStore;
private readonly global::StrawberryShake.IEntityIdSerializer _idSerializer;
private readonly global::StrawberryShake.Serialization.ILeafValueParser<global::System.Text.Json.JsonElement, global::System.String> _aParser;
private readonly global::StrawberryShake.Serialization.ILeafValueParser<global::System.Text.Json.JsonElement, global::System.String> _bParser;
public TestMultipleScalarBuilder(global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityIdSerializer idSerializer, global::StrawberryShake.IOperationResultDataFactory<global::Foo.Bar.ITestMultipleScalarResult> resultDataFactory, global::StrawberryShake.Serialization.ISerializerResolver serializerResolver)
{
_entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore));
_idSerializer = idSerializer ?? throw new global::System.ArgumentNullException(nameof(idSerializer));
ResultDataFactory = resultDataFactory ?? throw new global::System.ArgumentNullException(nameof(resultDataFactory));
_aParser = serializerResolver.GetLeafValueParser<global::System.Text.Json.JsonElement, global::System.String>("A") ?? throw new global::System.ArgumentException("No serializer for type `A` found.");
_bParser = serializerResolver.GetLeafValueParser<global::System.Text.Json.JsonElement, global::System.String>("B") ?? throw new global::System.ArgumentException("No serializer for type `B` found.");
}
protected override global::StrawberryShake.IOperationResultDataFactory<global::Foo.Bar.ITestMultipleScalarResult> ResultDataFactory { get; }
protected override global::StrawberryShake.IOperationResultDataInfo BuildData(global::System.Text.Json.JsonElement obj)
{
var entityIds = new global::System.Collections.Generic.HashSet<global::StrawberryShake.EntityId>();
global::StrawberryShake.IEntityStoreSnapshot snapshot = default !;
_entityStore.Update(session =>
{
snapshot = session.CurrentSnapshot;
});
return new TestMultipleScalarResultInfo(Deserialize_String(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "a")), Deserialize_String(global::StrawberryShake.Json.JsonElementExtensions.GetPropertyOrNull(obj, "b")), entityIds, snapshot.Version);
}
private global::System.String? Deserialize_String(global::System.Text.Json.JsonElement? obj)
{
if (!obj.HasValue)
{
return null;
}
return _aParser.Parse(obj.Value!);
}
}
Note how the "b" property is deserialized by Deserialize_String, which calls _aParser and not _bParser.
Steps to reproduce
See example query.
Relevant log output
No response
Additional Context?
No response
Version
latest source
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the generated TestMultipleScalarBuilder shown in the issue and reproduce the example query with scalar A and scalar B. Trace how the generated Deserialize_String method is selected and verify that each scalar property uses its own parser; done means the generated code no longer routes both properties through _aParser.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100