ChilliCream / graphql-platform

Welcome to the home of the Hot Chocolate GraphQL server for .NET, the Strawberry Shake GraphQL client for .NET and Banana Cake Pop the awesome Monaco based GraphQL IDE.
https://chillicream.com
MIT License
5.2k stars 742 forks source link

Example serializer from the Strawberry Shake documentation doesn't work #7575

Open samneefs opened 4 days ago

samneefs commented 4 days ago

Product

Strawberry Shake

Version

13.9.14

Link to minimal reproduction

https://filebin.net/gs6gkxscspus013d/GraphQlSerializerIssue.zip

Steps to reproduce

  1. Go to https://chillicream.com/docs/strawberryshake/v13/scalars#any-or-json
  2. Copy the example serializer:
    public class MyJsonSerializer : ScalarSerializer<JsonElement, object>
    {
    public MyJsonSerializer(string typeName = BuiltInScalarNames.Any)
        : base(typeName)
    {
    }
    public override object Parse(JsonElement serializedValue)
    {
        // handle the serialization of the JsonElement
    }
    protected override JsonElement Format(object runtimeValue)
    {
        // handle the serialization of the runtime representation in case
        // the scalar is used as a variable.
    }
    }
  3. Paste in a new class
  4. You'll get an error on protected override JsonElement Format(object runtimeValue)
  5. It is impossible to implement this method; it gives compiler error CS0462 since it tries to override two methods: protected abstract TSerialized Format(TRuntime runtimeValue); public object? Format(object? runtimeValue)

What is expected?

A working example

What is actually happening?

Compiler error

Relevant log output

No response

Additional context

No response

samneefs commented 4 days ago

I can't edit the label; it should be "Strawberry shake" instead of "hot chocolate".

samneefs commented 3 days ago

Additionally: the schema.extensions.graphql of the example is also not accepted:

extend scalar JSONObject
  @serializationType(name: "global::System.Object")
  @runtimeType(name: "global::System.Text.Json.JsonElement")

This gives a build error:

Severity    Code    Description Project File    Line    Suppression State   Details
Error (active)  MSB3073 The command "dotnet "C:\Users\**\.nuget\packages\strawberryshake.server\13.5.1\build\..\tools\net8\dotnet-graphql.dll" generate "C:\Users\**\source\repos\AccountantsAccademyConsole\Console2" -o "C:\Users\**\source\repos\AccountantsAccademyConsole\Console2\obj\Debug\net8.0\berry" -n Console2 -a md5 -t" exited with code -532462766. Console2    C:\Users\**\.nuget\packages\strawberryshake.server\13.5.1\build\StrawberryShake.Server.targets  79      

If I change the serializationType to "@serializationType(name: "global::System.String")", it would build, and would almost work, however the exclamation mark causes an error: return _jSONObjectParser.Parse(obj.Value.GetString()!); Without the exclamation mark it would be possible to do ToString on an object and use the parse methode that way: return _jSONObjectParser.Parse(obj.Value.GetString());

Ofcource I didn't actually want to use Object in the end, I wanted a dictionary, however this gives a whole lot of bad string replaces in the build, which ends up with an uncompilable client. eg.

     extend scalar JSONObject
                @serializationType(name: "global::System.String")
                @runtimeType(name: "global::System.Collections.Generic.Dictionary<global::string, global::string>")

This creates invalid methods like: private global::System.Collections.Generic.Dictionary<global::string, global::string>? Deserialize_Dictionary<global ::string, global::string >(global::System.Text.Json.JsonElement? obj)

The workaround that I finaly settled with, is a custom class, with a Dictionary property. The serializer writes to the custom class:

     extend scalar JSONObject
              @serializationType(name: "global::System.Text.Json.JsonElement")
              @runtimeType(name: "Console2.Models.JsonObject")`
public class MyJsonSerializer2 : ScalarSerializer<JsonElement, Console2.Models.JsonObject>
 {
    public MyJsonSerializer2()
            :base("JSONObject")
    {
    }
    public override Console2.Models.JsonObject Parse(JsonElement serializedValue)
    {
            var result = new Console2.Models.JsonObject();
            var json = serializedValue.GetRawText();
            result.Json = json;

            if (string.IsNullOrEmpty(json))
                return result;

            var dict = JsonConvert.DeserializeObject<Dictionary<global::System.String, global::System.String>>(json);
            result.keyValuePairs = dict;

            return result;
    }
    protected override JsonElement Format(Console2.Models.JsonObject runtimeValue)
    {
            var jsonElement = System.Text.Json.JsonSerializer.SerializeToElement(runtimeValue);
            //var json = jsonElement.GetRawText();

            return jsonElement;
    }
 }