Spring Boot GraphQL实现Map指定键查询的技术方案咨询
Absolutely! You can absolutely query specific keys from your Map<String, String> additionalData field using graphql-spqr-spring-boot-starter, and even use the exact query syntax you mentioned: { getData { additionalData { test1 } } }. Here's how to make it work smoothly:
1. Basic Setup (No Extra Configuration Needed)
By default, SPQR automatically maps Map types to GraphQL object types where the map's keys become queryable fields. All you need to do is properly expose the field in your entity class with SPQR's annotations:
public class YourDataEntity { private Map<String, String> additionalData; // Use @GraphQLQuery (or @GraphQLField in newer SPQR versions) to expose the getter @GraphQLQuery(name = "additionalData") public Map<String, String> getAdditionalData() { return additionalData; } // Setter for populating data (if required) public void setAdditionalData(Map<String, String> additionalData) { this.additionalData = additionalData; } }
Next, create a query resolver to return your entity:
@GraphQLApi public class DataQueryResolver { @GraphQLQuery(name = "getData") public YourDataEntity fetchData() { // Populate your entity with sample data YourDataEntity entity = new YourDataEntity(); Map<String, String> extraData = new HashMap<>(); extraData.put("test1", "value1"); extraData.put("test2", "value2"); entity.setAdditionalData(extraData); return entity; } }
With this setup, your desired GraphQL query will work out of the box:
{ getData { additionalData { test1 test2 } } }
2. Troubleshooting: If Dynamic Map Fields Don't Work
In rare cases (like older SPQR versions or conflicting custom configurations), you might need to explicitly configure the schema generator to use SPQR's built-in Map converters. Add this configuration bean to enforce the behavior:
@Configuration public class GraphQLConfiguration { @Bean public SchemaGenerator schemaGenerator(DataQueryResolver queryResolver) { return new SchemaGenerator() .withOperationsFromSingleton(queryResolver) // Enable default converters for Map-to-GraphQL-object conversion .withTypeMappingConfigurer(config -> config .withOutputConverters(new MapToOutputConverter()) .withInputConverters(new MapToInputConverter())) .withDefaults(); } }
3. Alternative: Explicit Key Query Method (For More Control)
If you want to add validation, default values, or custom logic when fetching map values, you can create a dedicated query method instead:
@GraphQLApi public class DataQueryResolver { // ... existing fetchData method ... @GraphQLQuery(name = "additionalDataValue") public String getAdditionalDataValue( @GraphQLContext YourDataEntity entity, @GraphQLArgument(name = "key") String key) { // Add custom logic here (e.g., validate key existence) return entity.getAdditionalData().getOrDefault(key, "No value found"); } }
This lets you query values like this:
{ getData { additionalDataValue(key: "test1") } }
Should You Switch to com.graphql-java?
If you hit unresolvable limitations with SPQR, switching to raw graphql-java is a valid choice—it gives you full manual control over schema wiring, so you could dynamically generate fields for your map keys using custom DataFetcher implementations. However, since SPQR is built on top of graphql-java and already handles map-to-dynamic-field conversion out of the box, it's worth getting this working first before making the switch.
内容的提问来源于stack exchange,提问作者Mateusz Sobczak

