티스토리 뷰
GraphQL의 정의하는 기본 scalar type은 아래와 같이 4가지 이다.
Int: A signed 32‐bit integer.
Float: A signed double-precision floating-point value.
String: A UTF‐8 character sequence.
Boolean: true or false.
이외의 type을 사용하기 위해서는
graphql-java에서 제공하는 GraphQLScalarType 사용하여 custom scalar type을 구현해야 한다.
이전에는 GraphQLScalarType을 상속받아서 구현하였으나
현재 해당 방식은 deprecated 되었고, 현재는 builder를 사용해야 한다.
json 형태의 data를 추가한다면 아래와 같이 builder를 사용할 수 있다.
(sample code는 kotlin으로 구현되었음)
GraphQLScalarType
.newScalar()
.name("JSON")
.description("com.fasterxml.jackson.databind.JsonNode")
.coercing(object : Coercing<ObjectValue, JsonNode> {
@Throws(CoercingSerializeException::class)
override fun serialize(dataFetcherResult: Any): JsonNode {
return if (dataFetcherResult is JsonNode) {
dataFetcherResult
} else {
throw CoercingSerializeException("Unable to serialize " + dataFetcherResult
+ ". Wrong Type. Expected JsonNode.class, Got " + dataFetcherResult.javaClass
)
}
}
@Throws(CoercingParseValueException::class)
override fun parseValue(input: Any): ObjectValue {
return if (input is ObjectValue) {
input
} else {
throw CoercingParseValueException("Unable to parseValue " + input
+ ". Wrong Type. Expected ObjectValue.class, Got " + input.javaClass
)
}
}
@Throws(CoercingParseLiteralException::class)
override fun parseLiteral(input: Any): ObjectValue {
return if (input is ObjectValue) {
input
} else {
throw CoercingParseLiteralException("Unable to parseLiteral " + input
+ ". Wrong Type. Expected ObjectValue.class, Got " + input.javaClass
)
}
}
})
.build()
Builder method 중 다음과 같이 3가지를 사용한다.
@Override
public Builder name(String name) {
super.name(name);
return this;
}
@Override
public Builder description(String description) {
super.description(description);
return this;
}
public Builder coercing(Coercing coercing) {
this.coercing = coercing;
return this;
}
name(String name) : graphql schema 에서 사용하기 위한 이름을 정의
description(String description) : 어디서 사용되는지 아직 못찾았음 (인터넷에서 찾은 다양한 예제들에서 대부분 구현)
coercing(Coercing coercing) : input, output 데이터를 정의하고 serialize, parse 를 위한 구현을 제공
Coercing은 graphql-java library에서 제공하는 interface 이며
아래와 같이 Input 타입(client에서 받는 type )과, Output 타입(server가 return하는 type)을 정의하게 되어 있다.
public interface Coercing<I, O>
Coercing interface의 abstract method는 다음과 같다.
O serialize(Object dataFetcherResult) throws CoercingSerializeException;
I parseValue(Object input) throws CoercingParseValueException;
I parseLiteral(Object input) throws CoercingParseLiteralException;
serialize : dataFetcherResult의 결과로 return되는 java object를 scalar type 에 맞게 변환하기 위한 메소드
parseValue : query에서 값을 parsing 할 때 사용되는 메소드
parseLiteral : 요청받은 query를 validation 할 때 사용되는 메소드
예제의 경우 input은 ObjectValue, output은 JsonNode로 정의하였다.
(graphql-java를 사용하는 경우 query에 있는 json type은 ObjectValue class로 읽어들인다.)
위의 serialize 예제에서는 resolver에서 JsonNode를 return 한다는 가정하에 class type 만 확인하고 그대로 return 하였으나
만약 resolver에서 다른 type을 return 한다면 converting 작업을 구현해야 한다.
예를 들어서 resolver에서 String 형태로 json 을 return 한다면
serialize는 다음과 같이 구현될 것이다.
@Throws(CoercingSerializeException::class)
override fun serialize(dataFetcherResult: Any): JsonNode {
return if (dataFetcherResult is String) {
ObjectMapper().readTree(dataFetcherResult)
} else {
throw CoercingSerializeException("Unable to serialize " + dataFetcherResult
+ ". Wrong Type. Expected String.class, Got " + dataFetcherResult.javaClass
)
}
}
위와 같이 custom scalar type을 정의하면
GraphQL Configuration에서 아래와 같이 추가를 해줘야 한다.
@Configuration
class GraphQLConfig {
@Bean
fun scalars(): Array = arrayOf(customJson)
...
}
val customJson : GraphQLScalarType = GraphQLScalarType
.newScalar()
.name("JSON")
.description("com.fasterxml.jackson.databind.JsonNode")
.coercing(object : Coercing<ObjectValue, JsonNode> {
@Throws(CoercingSerializeException::class)
override fun serialize(dataFetcherResult: Any): JsonNode {
return if (dataFetcherResult is JsonNode) {
dataFetcherResult
} else {
throw CoercingSerializeException("Unable to serialize " + dataFetcherResult
+ ". Wrong Type. Expected JsonNode.class, Got " + dataFetcherResult.javaClass
)
}
}
@Throws(CoercingParseValueException::class)
override fun parseValue(input: Any): ObjectValue {
return if (input is ObjectValue) {
input
} else {
throw CoercingParseValueException("Unable to parseValue " + input
+ ". Wrong Type. Expected ObjectValue.class, Got " + input.javaClass
)
}
}
@Throws(CoercingParseLiteralException::class)
override fun parseLiteral(input: Any): ObjectValue {
return if (input is ObjectValue) {
input
} else {
throw CoercingParseLiteralException("Unable to parseLiteral " + input
+ ". Wrong Type. Expected ObjectValue.class, Got " + input.javaClass
)
}
}
})
.build()
GraphQL Schema 파일에서는 다음과 같이 scalar를 정의하고 사용할 수 있다.
("JSON Type"은 GraphiQL에서 Schema를 확인할 때 description 에 표시되는 내용이다.)
"JSON Type"
scalar JSON
## Query
type Query {
getJsonValue(value: JSON): JSON
}
Input으로 들어오는 ObjectValue는 아래와 같이 ObjectField array 를 가지고 있으며,
getObjectFields()를 사용하여 해당 값을 가져올 수 있다.
private final List objectFields = new ArrayList<>();
public List getObjectFields() {
return new ArrayList<>(objectFields);
}
ObjectField는 아래와 같이 name, value를 가지고 있으며,
getName(), getValue()를 사용하여 값을 가져올 수 있다.
private final String name;
private final Value value;
public String getName() {
return name;
}
public Value getValue() {
return value;
}
아래와 같이 for 문으로 입력받은 json 의 값을 확인할 수 있다.
for (tmp: ObjectField in value.objectFields) {
println("${tmp.name}, ${tmp.value}")
}
'Development' 카테고리의 다른 글
[PostgreSQL] JPA에서 Pageable 옵션을 사용하여 raw query 호출시 collate 설정하기 (0) | 2020.03.28 |
---|---|
[GraphQL] graphql-java library 사용시 custom exception 추가하기 (0) | 2020.03.22 |
[PostgreSQL] 한글 정렬 시 collate 옵션 사용하기 (0) | 2020.03.01 |
[PostgreSQL] trigger 사용하기 (history table 만들기) (0) | 2019.09.12 |
[PostgreSQL] stored function(stored procedures) 사용하기 (2) | 2019.09.08 |
- Total
- Today
- Yesterday
- 퇴근길인문학수업
- 개리비숍
- 재테크
- 오건영
- 가나출판사
- 자기개발
- 토니로빈스
- 책리뷰
- 투자
- 더숲
- sethgodin
- graphql-java
- 유발하라리
- 메이트북스
- 알에이치코리아
- 독서
- 사경인
- 송희구
- 서삼독
- PostgreSQL
- 강형욱
- 경제
- 블랙피쉬
- graphql
- 한빛비즈
- aws 자격증
- docker
- ebs다큐프라임
- 백상경제연구원
- 인류3부작
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |