Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип предназначен для представления неделимого значения.
GraphQL по умолчанию предоставляет определенные скалярные типы, такие как String, Int, Float и т.д., но обычно разработчикам требуются пользовательские скаляры. В этой статье мы рассмотрим, как их можно создать
Сначала нам необходимо объявить пользовательские скаляры в файле схемы.
В данном примере мы будем использовать скаляр даты, имеющий вид yyyy-mm-dd. Ниже показано, как можно определить скаляр.
Scalar Date
Затем мы можем использовать его в любом поле. В этом примере мы добавим новое поле publishedTime для объекта book и определим его тип как Date
type Book { id: ID! name: String! pageCount: Int! price: Int! author: Author! publishedDate:Date! }
Теперь нам необходимо определить, как движок graphql может сериализовать и десериализовать этот скаляр.
Мы создадим конфигурационный файл ScalarConfig, в котором будет храниться конфигурация для скаляров, и определим объект GraphQLScalarType.
public static final GraphQLScalarType DateScalar = GraphQLScalarType.newScalar() .name("Date") .description("A custom scalar that handles Date")
Spring использует значение, предоставленное в методе name, чтобы знать, какой объект отвечает за тип скаляра. В нашем случае это Date
public static final GraphQLScalarType DateScalar = GraphQLScalarType.newScalar() .name("Date") .description("A custom scalar that handles Date") .coercing(new Coercing() { @Override public Object serialize(@NotNull Object dataFetcherResult, @NotNull GraphQLContext graphQLContext, @NotNull Locale locale) throws CoercingSerializeException { try { Instant publishedTime = (Instant) dataFetcherResult; DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE.withZone(ZoneId.systemDefault()); return formatter.format(publishedTime); } catch (CoercingSerializeException exception) { throw new CoercingSerializeException("Invalid Input:"+exception.getMessage()); } }
Acest bloc de cod indică modul în care se serializează tipul scalar. În codul nostru java, câmpul publishedTime este de tip Instant, dar serverul se așteaptă la un scalar de tip Date. Prin urmare, convertim un tip instantaneu într-un scalar de dată folosind această metodă.
Rezultatul interogării pentru un bookDetails arată în felul următor.
{ "data": { "bookById": { "publishedDate": "2020-01-23" } } }
În obiectul Book, data publicată arată astfel:2020-01-23T15:04:01Z
Аналогично у нас есть новый мутационный api под названием updateBookPublishedDate, который позволяет обновить дату публикации книги. В качестве второго аргумента он принимает дату, тип которой - Date. Нам необходимо преобразовать этот аргумент в Instant.
@Override public Object parseValue(@NotNull Object input, @NotNull GraphQLContext graphQLContext, @NotNull Locale locale) throws CoercingParseValueException { try{ return LocalDate.parse((String) input).atStartOfDay(ZoneId.systemDefault()).toInstant(); } catch (RuntimeException exception) { throw new CoercingParseValueException("Invalid Input:"+exception.getMessage()); } } @Override public Object parseLiteral(@NotNull Value input, @NotNull CoercedVariables variables, @NotNull GraphQLContext graphQLContext, @NotNull Locale locale) throws CoercingParseLiteralException { try { StringValue stringValue = (StringValue) input; LocalDate date = LocalDate.parse(stringValue.getValue()); return date.atStartOfDay(ZoneId.systemDefault()).toInstant(); } catch (RuntimeException exception) { throw new CoercingParseLiteralException("Invalid Input:"+exception.getMessage()); } }
В этом нам помогут два метода
Для более детального понимания рассмотрим пример:
mutation updateBooK($date:Date!) { updateBookPublishedDate(id:"book-1", date:$date){ price publishedDate } }
Здесь значение даты является входным объектом переменной, т.е. оно будет передано под объектом переменных graphql в виде this:
{ "date": "2021-09-10" }
Поэтому в данном случае будет вызван parseValue
mutation{ updateBookPublishedDate(id:"book-1", date:"2021-06-12"){ price publishedDate } }
Здесь мы инлайним значение поля date. В этом случае будет вызван parseLiteral.
Здесь мы инлайним значение поля date. В этом случае будет вызван parseLiteral.
Теперь нам нужно подключить этот скаляр к конфигурации Spring, чтобы она могла регистрировать и использовать скаляр.
@Bean public RuntimeWiringConfigurer runtimeWiringConfigurer() { return builder -> builder.scalar(DateScalar); }
Как всегда, блок кода можно найти в github link.
20.08.2023 18:21
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в 2023-2024 годах? Или это полная лажа?".
20.08.2023 17:46
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
19.08.2023 18:39
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в частности, магию поплавков и гибкость flexbox.
19.08.2023 17:22
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для чтения благодаря своей простоте. Кроме того, мы всегда хотим проверить самые последние возможности в наших проектах!
18.08.2023 20:33
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий их языку и культуре.
05.08.2023 16:43
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции обеспечивают мощный способ выполнения операций на битовом уровне, предлагая более эффективные решения для определенных задач. В этом блоге мы рассмотрим, как...