如何在 GraphQL Mutation 中傳回任意數據
1. 簡介
在使用 GraphQL 突變時,我們經常會遇到返回固定類型過於受限的情況。例如,有時我們可能希望傳回一條簡單的成功訊息,有時又希望根據輸入或業務邏輯傳回詳細的物件。
在本教程中,我們將探討如何使用 Java 從 GraphQL 變異中傳回anydata
。
2. 理解anydata
在 GraphQL 的上下文中, anydata
指的是突變可以傳回給客戶端的任何類型的值。
這可能會因用例或突變中的邏輯而異。例如,突變可能會返回:
- 一則簡單訊息(
String
) - 複雜物件(例如
User
) - 包含多個欄位的自訂包裝器
GraphQL 沒有像 JavaScript 的any
這樣的內建類型,因此我們定義模式以允許靈活的回傳類型。
3. 定義 GraphQL Schema
設定好依賴項後,我們繼續定義 GraphQL 模式。在這裡,我們描述突變的結構以及它可以返回的資料類型。
我們將在src/main/resources
目錄下建立一個名為schema.graphqls
的檔案:
type Mutation {
updateProfile(name: String!, type: String!): AnydataResponse
}
union AnydataResponse = SimpleMessage | UserProfile
type SimpleMessage {
message: String!
}
type UserProfile {
id: ID!
name: String!
status: String!
}
在這個範例中,我們定義了一個名為updateProfile
的突變。根據輸入,該突變可能會傳回簡單訊息或詳細的使用者資料。由於傳回類型可能有所不同,我們使用 GraphQL 中的union
類型來支援單一名稱下的多種返回類型。
4.用Java創建模型
現在我們已經定義了 GraphQL 模式,接下來讓我們為每種 GraphQL 類型建立對應的 Java 類別。這些模型代表了updateProfile
突變的可能回傳值。
我們將建立以下類別:
- 標記介面
AnydataResponse
-
SimpleMessage
-
UserProfile
4.1. 標記介面 – AnydataResponse
由於 GraphQL 聯合映射到多種 Java 類型,因此我們使用兩種返回類型都實現的通用標記介面:
public interface AnydataResponse {
}
此接口沒有任何方法。它僅用於告知 GraphQL Java, SimpleMessage
和UserProfile
都是AnydataResponse
union
的有效類型。
4.2. SimpleMessage
此類別包含一個基本的String
訊息:
public class SimpleMessage implements AnydataResponse {
private String message;
// constructor, setters and getters
}
4.3. UserProfile
此類代表用戶設定檔:
public class UserProfile implements AnydataResponse {
private String id;
private String name;
private String status;
//constructor, setters and getters
}
5. 實作變異解析器
現在我們已經建立了模型類,讓我們用 Java 實作實際的變異邏輯。在這裡,我們定義當客戶端呼叫updateProfile
變異時會發生什麼:
public DataFetcher<AnydataResponse> updateProfile() {
return new DataFetcher<AnydataResponse>() {
@Override
public AnydataResponse get(DataFetchingEnvironment environment) {
String name = environment.getArgument("name");
String type = environment.getArgument("type");
if ("message".equalsIgnoreCase(type)) {
return new SimpleMessage("Profile updated for: " + name);
} else if ("user".equalsIgnoreCase(type)) {
return new UserProfile("123", name, "ACTIVE");
} else {
return new SimpleMessage("Unknown type provided.");
}
}
};
}
在此範例中,我們定義了一個名為updateProfile()
的方法,該方法傳回一個DataFetcher
,這是在 GraphQL Java 中實現自訂邏輯的標準方法。在DataFetcher
的get()
方法中,我們檢索客戶端在呼叫突變時傳入的name
和type
參數。
然後,我們使用type
值來決定傳回哪種類型的回應。如果 type 的值為“ message
”,我們將建立並傳回一個包含簡短確認訊息的SimpleMessage
物件。另一方面,如果 type 為“ user
”,我們將傳回一個完整的UserProfile
物件。
6. 測試突變
現在,我們將設定 GraphQL 引擎,將模式連結到解析器,並編寫一個基本的單元測試以確保變異返回預期結果。
讓我們從初始化 GraphQL 實例的配置類別開始:
@Bean
public GraphQL graphQL() {
SchemaParser schemaParser = new SchemaParser();
SchemaGenerator schemaGenerator = new SchemaGenerator();
TypeDefinitionRegistry typeRegistry = schemaParser.parse(
new InputStreamReader(getClass().getResourceAsStream("/schema.graphqls"))
);
RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring()
.type("Mutation", builder ->
builder.dataFetcher("updateProfile", new MutationResolver().updateProfile()))
.build();
GraphQLSchema schema = schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring);
return GraphQL.newGraphQL(schema).build();
}
接下來,我們可以使用基本單元測試來驗證突變:
String mutationMsg = "mutation { updateProfile(name: \"Alice\", type: \"message\") { ... on SimpleMessage { message } } }";
String mutationUser = "mutation { updateProfile(name: \"Bob\", type: \"user\") { ... on UserProfile { id name status } } }";
ExecutionResult result = graphQL.execute(ExecutionInput.newExecutionInput().query(mutationMsg).build());
Map<String, Object> data = result.getData();
Map<String, Object> updateProfile = (Map<String, Object>) data.get("updateProfile");
assertEquals("Profile updated for Alice", updateProfile.get("message"));
ExecutionResult result = graphQL.execute(ExecutionInput.newExecutionInput().query(mutationUser).build());
data = result.getData();
userProfile = (Map<String, Object>) data.get("updateProfile");
assertEquals("Bob", userProfile.get("name"));
assertEquals("ACTIVE", userProfile.get("status"));
在這些範例中,我們使用不同的輸入值來呼叫updateProfile
突變來測試回傳類型。 「 … on
」語法使用 GraphQL 的內聯片段根據實際傳回類型( SimpleMessage
或UserProfile
提取欄位。
7. 結論
在本文中,我們探討如何使用聯合和自訂邏輯從 GraphQL 突變中傳回anydata
。這種方法使我們的 API 更加靈活,能夠輕鬆處理各種回應類型。
與往常一樣,原始碼可在 GitHub 上取得。