如何在Java中通过代码获取GraphQL查询的枚举参数可选值?
使用graphql-java获取GraphQL枚举值并动态构建查询
1. 查询GraphQL Schema获取枚举可选值
要获取上游API中枚举类型的可选值,有两种主流方式:通过自省查询远程获取Schema,或者解析上游提供的本地SDL格式Schema文件。
方式一:通过自省查询远程获取Schema
如果上游API开启了自省功能,可以执行标准自省查询获取完整Schema定义,再从中提取目标枚举值:
import graphql.introspection.IntrospectionQuery; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; // 1. 构造并发送自省查询 String introspectionQuery = IntrospectionQuery.INTROSPECTION_QUERY; GraphQLRequest request = GraphQLRequest.newRequest().query(introspectionQuery).build(); String responseJson = sendGraphQLRequest(request); // 2. 解析自省响应 ObjectMapper objectMapper = new ObjectMapper(); IntrospectionResult introspectionResult = objectMapper.readValue(responseJson, IntrospectionResult.class); // 3. 定位目标枚举类型(替换为上游定义的枚举名称,比如CountryEnum) Optional<Introspection.Type> countryEnumType = introspectionResult.getTypes().stream() .filter(type -> type.getKind() == Introspection.TypeKind.ENUM) .filter(type -> "CountryEnum".equals(type.getName())) .findFirst(); // 4. 提取所有枚举值 if (countryEnumType.isPresent()) { List<String> countryValues = countryEnumType.get().getEnumValues().stream() .map(Introspection.EnumValue::getName) .collect(Collectors.toList()); // countryValues即为country参数的所有可选值 }
方式二:解析本地SDL Schema文件
如果上游API关闭了自省,可使用上游提供的SDL文件(.graphqls)直接本地解析:
import graphql.schema.GraphQLSchema; import graphql.schema.GraphQLEnumType; import graphql.schema.idl.SchemaParser; import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; import java.util.stream.Collectors; // 加载本地SDL文件 String schemaSDL = Files.readString(Paths.get("path/to/upstream-schema.graphqls")); GraphQLSchema schema = SchemaParser.newParser() .schemaString(schemaSDL) .build() .parse(); // 提取目标枚举值 GraphQLEnumType countryEnum = (GraphQLEnumType) schema.getType("CountryEnum"); List<String> countryValues = countryEnum.getValues().stream() .map(GraphQLEnumValueDefinition::getName) .collect(Collectors.toList());
2. 动态构建GraphQL查询
拿到枚举值后,可根据业务需求动态生成查询语句和变量,比如遍历枚举值执行单参数查询,或者构建批量查询一次性请求多枚举值数据。
示例1:遍历枚举值执行单参数查询
// 定义查询模板 String queryTemplate = """ query GetCountryData($country: CountryEnum!) { countryInfo(country: $country) { id name population } } """; // 遍历所有枚举值构建请求 for (String country : countryValues) { var variables = Map.of("country", country); GraphQLQueryRequest queryRequest = GraphQLRequest.newRequest() .query(queryTemplate) .variables(variables) .build(); // 后续执行请求(见下文) }
示例2:构建批量查询一次性请求
如果上游API支持接收枚举列表参数,可生成批量查询:
// 构建批量查询语句 String batchQuery = """ query GetMultiCountryData($countries: [CountryEnum!]!) { multiCountryInfo(countries: $countries) { id name country } } """; // 构造包含所有枚举值的变量 var variables = Map.of("countries", countryValues); GraphQLQueryRequest batchRequest = GraphQLRequest.newRequest() .query(batchQuery) .variables(variables) .build();
3. 提交查询并执行结果解析
实现HTTP请求工具方法,将构建好的查询提交到上游API,并解析返回结果:
import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import java.io.IOException; import com.fasterxml.jackson.databind.ObjectMapper; // 发送GraphQL请求的工具方法 private String sendGraphQLRequest(GraphQLRequest request) throws IOException { OkHttpClient client = new OkHttpClient(); ObjectMapper objectMapper = new ObjectMapper(); String requestJson = objectMapper.writeValueAsString(request); RequestBody body = RequestBody.create( requestJson, okhttp3.MediaType.parse("application/json") ); Request httpRequest = new Request.Builder() .url("https://your-upstream-api-url/graphql") // 替换为上游API地址 .post(body) .addHeader("Content-Type", "application/json") // 按需添加认证头,比如Authorization: Bearer xxx .build(); try (Response response = client.newCall(httpRequest).execute()) { assert response.body() != null; return response.body().string(); } } // 执行查询并解析结果 String responseJson = sendGraphQLRequest(queryRequest); CountryInfoDto result = objectMapper.readValue(responseJson, CountryInfoDto.class);
注意事项
- 确认上游API是否开启自省:部分生产环境API会关闭自省,此时必须使用本地SDL文件。
- 匹配枚举值格式:GraphQL枚举值通常为大写或驼峰形式,需与API定义完全一致,避免请求报错。
- 处理认证权限:根据上游要求添加认证头,确保请求有权限访问Schema和数据接口。
内容的提问来源于stack exchange,提问作者Ajit
相关产品推荐
相关产品推荐

