Skip to content

Customize scalar type serialization #413

@benneq

Description

@benneq

Currently it's very hard to use custom Value Objects with ID Scalars. Or in general: to provide custom serialization for any kind of generics / class inheritance.

Schema:

type Query {
    bookById(id: ID): ID
}

Controller:

@Controller
public class BookController {

    @QueryMapping
    Mono<BookId> bookById(@Argument BookId id) {
        return Mono.just(id);
    }

    // this is called for `@Argument BookId` and works as expected
    @Bean
    Converter<String, BookId> stringToBookIdConverter() {
        return new Converter<String, BookId>() {
            @Override
            public BookId convert(String source) {
                return new BookId(source);
            }
        };
    }

    // this is not working
    @Bean
    Converter<BookId, String> bookIdToStringConverter() {
        return new Converter<BookId, String>() {
            @Override
            public String convert(BookId source) {
                return source.value(); // this is not called
            }
        };
    }
}
public record BookId(String value) {
    @Override
    public String toString() {
        return "don't use this for serialization"; // instead this is called by GraphqlIDCoercing.serialize
    }
}

As a workaround I could implement a custom BookId scalar, with a matching scalar coercing, but this will lead to new problems:

interface Node {
  id: ID
}

type Book implements Node {
  id: BookId # ERROR, because the Node interface wants the ID scalar
}

Another workaround would be to use RuntimeWiringConfigurer and override the default ID scalar and provide a custom serialize implementation that doesn't use toString(). But that's hard to use, especially if you want to dynamically provide new classes with custom serialization.

The code in graphql.execution.ExecutionStrategy does not seem to provide a way to customize the serialization. Or maybe I have missed something in the code or the docs.

Is there already a (easy) way to do this?

Metadata

Metadata

Assignees

Labels

status: declinedA suggestion or change that we don't feel we should currently apply

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions