Skip to content

User scalars

Stanislav Silin edited this page Jul 16, 2023 · 2 revisions

With ZeroQL, you can map GraphQL scalars into C# classes. There are two ways to do it. First, just generate a ZeroQL GraphQL client. By default, all custom scalars will be mapped into stubs like that:

public sealed record Instant : ZeroQLScalar
{
    public Instant()
    {
    }

    public Instant(string value)
    {
        Value = value;
    }

    public static implicit operator Instant(string value) => new Instant(value);
    public static implicit operator string (Instant scalar) => scalar.Value;
}

If you don't have any special requirements for a scalar, then this way is for you.

The second way allows you to define complex mappings for your scalars. For example, we have a schema with scalar Instant:

schema {
  query: Query
}
  
type Query {
  instant: Instant!
}

"Represents an instant on the global timeline, with nanosecond resolution."
scalar Instant

We can create a C# class and JSON serializer and add mapping for it:

public class Instant
{
    public DateTimeOffset DateTimeOffset { get; set; }
}

public class InstantConverter : JsonConverter<Instant?>
{
    public override Instant? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var instant = reader.GetString();
        return new Instant { DateTimeOffset = DateTimeOffset.Parse(instant!) };
    }

    public override void Write(Utf8JsonWriter writer, Instant? value, JsonSerializerOptions options)
    {
        var instant = value.DateTimeOffset.ToString("yyyy-MM-ddTHH:mm:ssZ");
        writer.WriteStringValue(instant);
    }
}

public static class Module
{
    [ModuleInitializer]
    public static void Initialize()
    {
        // don't forget to add serializer to ZeroQL json options
        ZeroQLJsonOptions.Configure(o => o.Converters.Add(new InstantConverter()));
    }
}

Then during generation, pass parameter --scalars Instant=MyApp.Instant or set property scalars in zeroql.json config file

"scalars": {
    "Instant": "MyApp.Instant"
}

It will replace the GraphQL scalar with the correct type in generated GraphQL client.