在GraphQL類型系統中,類型樹的葉子節點成爲Scalar。一旦訪問到了Scalar類型的數據,就沒法在該類型基礎上進一步訪問其下的類型層次結構。Scalar類型意味着該類型的值沒法再細分。java
在GraphQL規範中,要求其全部實現都必須具備以下Scalar類型:ide
GraphQL - Java補充添加了以下幾種額外類型:編碼
graphql.Scalars類中包含了全部現有的scalar類型的單例實例。scala
能夠自定義Scalar類型。在這種實現方式下,須要在運行時本身實現數據到類型的映射機制。code
假設咱們有一個email的scalar類型,它將使用email地址做爲輸出和輸出。對象
建立一個EMAIL的scalar類型以下:ci
public static final GraphQLScalarType EMAIL = new GraphQLScalarType("email", "A custom scalar that handles emails", new Coercing() { @Override public Object serialize(Object dataFetcherResult) { return serializeEmail(dataFetcherResult); } @Override public Object parseValue(Object input) { return parseEmailFromVariable(input); } @Override public Object parseLiteral(Object input) { return parseEmailFromAstLiteral(input); } });
自定義的scalar視線中,核心工做是數據映射的實現部分。主要須要實現以下三個方法:get
自定義的scalar中,必需要實現兩個input的轉換(parseValue / parseLiteral)和一個output的轉換(serialize)。input
例如,對於以下的執行語句:graphql
mutation Contact($mainContact: Email!) { makeContact(mainContactEmail: $mainContact, backupContactEmail: "backup@company.com") { id mainContactEmail } }
自定義的Email類型scalar將會有以下調用:
scalar定義中也能夠驗證輸入或輸出的數據是否有效。例如:email是不是有效的email數據類型。
graphql.schema.Coercing中有以下規定:
有些人視圖依賴runtime exception來實現驗證,而後指望它們以graphql error形式輸出。但事實並非這樣。在自定義Scalar時,必須遵循Coercing方法的規範,才能使GraphQL - Java正確運行。
下面是一個複雜的Email類新的Scalar實現。
public static class EmailScalar { public static final GraphQLScalarType EMAIL = new GraphQLScalarType("email", "A custom scalar that handles emails", new Coercing() { @Override public Object serialize(Object dataFetcherResult) { return serializeEmail(dataFetcherResult); } @Override public Object parseValue(Object input) { return parseEmailFromVariable(input); } @Override public Object parseLiteral(Object input) { return parseEmailFromAstLiteral(input); } }); private static boolean looksLikeAnEmailAddress(String possibleEmailValue) { // ps. I am not trying to replicate RFC-3696 clearly return Pattern.matches("[A-Za-z0-9]@[.*]", possibleEmailValue); } private static Object serializeEmail(Object dataFetcherResult) { String possibleEmailValue = String.valueOf(dataFetcherResult); if (looksLikeAnEmailAddress(possibleEmailValue)) { return possibleEmailValue; } else { throw new CoercingSerializeException("Unable to serialize " + possibleEmailValue + " as an email address"); } } private static Object parseEmailFromVariable(Object input) { if (input instanceof String) { String possibleEmailValue = input.toString(); if (looksLikeAnEmailAddress(possibleEmailValue)) { return possibleEmailValue; } } throw new CoercingParseValueException("Unable to parse variable value " + input + " as an email address"); } private static Object parseEmailFromAstLiteral(Object input) { if (input instanceof StringValue) { String possibleEmailValue = ((StringValue) input).getValue(); if (looksLikeAnEmailAddress(possibleEmailValue)) { return possibleEmailValue; } } throw new CoercingParseLiteralException( "Value is not any email address : '" + String.valueOf(input) + "'" ); } }