GraphQL使用之graphql-java自定义标量类型
Posted NetWhite
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GraphQL使用之graphql-java自定义标量类型相关的知识,希望对你有一定的参考价值。
前言
在再谈GraphQL之在spring boot项目中快速应用中,我们写了一个demo工程,业务逻辑以查询项目信息为例。本文会继续以这个demo作为说明进行相关补充,demo地址:https://github.com/xxd763795151/graphql.demo。
何谓“标量”
在GrapQL中,标量类型指的是类型系统的叶子节点,在进行查询的时候,不能进行更深层次的查询,表示的是一个不可再分割的值。
类比java语言,可以看作是一个“基本类型”,但这种说法又不太正确,因为GraphQL可以自定义一些复杂对象作为标量类型,这和java又完全不一样。
如下定义,ID和String就是GraphQL的标量类型
# 定义项目字段
type Item {
id: ID!
code: String!
name: String!
}
默认标量类型
GraphQL默认自带的标量类型如下:
Int
:有符号 32 位整数。Float
:有符号双精度浮点值。String
:UTF‐8 字符序列。Boolean
:true
或者false
。ID
:ID 标量类型表示一个唯一标识符,通常用以重新获取对象或者作为缓存中的键。ID 类型使用和 String 一样的方式序列化;然而将其定义为 ID 意味着并不需要人类可读型。
但是这几个基本类型,完全无法满足我们常规的业务开发,比如我现在想在上面的Item里的加上一个createTime字段,是一个Long类型,返回项目创建的时间戳,就不支持:
在idea中直接标红。
自定义标量类型
Schema定义标量类型
# 自定义标量类型:Long
scalar Long
这里定义到了base.graphqls文件中。
java配置已实现的标量类型
graphql-java额外提供了以下几种标量类型,分别对应java的类:
- Long ---> java.lang.Long
- Short ---> java.lang.Short
- Byte ---> java.lang.Byte
- BigDecimal ---> java.math.BigDecimal
- BigInteger ---> java.math.BigInteger
在以上5种标量的使用中,我们不需要再额外针对其类型开发序列化、反序列化等相关代码,但是在上面的demo中使用的依赖及初始化方式中还是要定义下相关类型,定义的方式也很简单,如下,增加一行代码:
这样便完成了Long标量类型的定义,其它几种类型方式一样,只需将其中的GraphqlLongCoercing类替换为相对应的即可。
启动工程作一下测试,查询createTime字段,结果预期:
顺便再说明下,demo中的依赖如下,对号入座:
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>11.0.1</version>
</dependency>
java定义未实现的标量类型
如果需要定义一些graphql-java未提供的标量类型,需要自已实现该类型的序列化及解析等方法。
现在我给Item再增加一个searchDate字段,是一个Date类型,返回项目搜索时的日期(格式:yyyy-MM-dd HH:mm:ss),因此我们需要新增一个名为Date的标量类型,如下:
# 自定义日期类型,日期格式 yyyy-MM-dd HH:mm:ss
scalar Date
# 定义项目字段
type Item {
id: ID!
code: String!
name: String!
createTime: Long
searchDate: Date
}
定义Date标量字段的java代码如下:
public class GraphQLScalarDateType extends GraphQLScalarType {
private static final String NAME = "Date";
private static final String PATTERN = "yyyy-MM-dd HH:mm:ss";
private static final String DESCRIPTION = "Date scalar: " + PATTERN;
private static final DateFormat DATE_FORMAT = new SimpleDateFormat(PATTERN);
public GraphQLScalarDateType() {
this(NAME, DESCRIPTION, new DateCoercing());
}
public GraphQLScalarDateType(String name, String description, Coercing coercing) {
super(name, description, coercing);
}
static class DateCoercing implements Coercing<Date, String> {
// 输出序列化,返回查询结果
@Override public String serialize(Object dataFetcherResult) throws CoercingSerializeException {
return DATE_FORMAT.format(dataFetcherResult);
}
// 输入,将查询参数转换为运行时的java对象
@Override public Date parseValue(Object input) throws CoercingParseValueException {
String dateStr = String.valueOf(input);
try {
return DATE_FORMAT.parse(dateStr);
} catch (ParseException e) {
throw new CoercingParseValueException("Can not parse: " + dateStr + " as a Date object");
}
}
@Override public Date parseLiteral(Object input) throws CoercingParseLiteralException {
String dateStr = String.valueOf(input);
try {
return DATE_FORMAT.parse(dateStr);
} catch (ParseException e) {
throw new CoercingParseValueException("Can not parse: " + dateStr + " as a Date object");
}
}
}
}
最后在构造GraphQL实例的时候配置上该类型即可。
查看效果:
末语
本文示例的完整代码已提交github: https://github.com/xxd763795151/graphql.demo。
以上是关于GraphQL使用之graphql-java自定义标量类型的主要内容,如果未能解决你的问题,请参考以下文章
graphql-java 中的 GraphQL 模式定义语言支持