The Simplest Solution for Dynamic Fields in Spring Boot APIs
This article demonstrates how to use Jackson’s @JsonMixin and @JsonFilter annotations together with a custom ObjectMapper and PropertyFilter in Spring Boot 3.5.0 to control API response fields dynamically via request parameters, avoiding multiple DTOs or heavyweight GraphQL setups.
When building front‑back separated services, different endpoints or user permissions often require returning only a subset of an entity’s fields. Traditional approaches involve creating many VO/DTO classes, which leads to code duplication, or adopting GraphQL, which adds learning and integration overhead. This article shows a lightweight alternative based on Jackson’s serialization features.
Environment : Spring Boot 3.5.0.
1. Define the domain object that will be filtered:
public class User {
private Long id;
private String name;
private Integer age;
private String idNo;
private String phone;
// getters, setters, constructors
}2. Create a mixin class that attaches a filter to the target type without modifying the original POJO:
@JsonMixin(type = {User.class})
@JsonFilter("dynamicField")
public class ObjectDynamicFieldMixin {
}The @JsonMixin annotation tells Jackson to treat User as if it were annotated with @JsonFilter("dynamicField").
3. Configure a custom ObjectMapper to register the filter:
@Configuration
public class JacksonConfig {
@Bean
Jackson2ObjectMapperBuilderCustomizer registrarFilterProvider() {
return builder -> {
SimpleFilterProvider filter = new SimpleFilterProvider()
.addFilter("dynamicField", new DynamicFieldFilter());
builder.filters(filter);
};
}
}Note that the filter name ( "dynamicField") must be identical to the name used in ObjectDynamicFieldMixin.
4. Implement the filter logic by extending SimpleBeanPropertyFilter:
public class DynamicFieldFilter extends SimpleBeanPropertyFilter {
@Override
protected boolean include(PropertyWriter writer) {
ServletRequestAttributes requestAttributes =
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
if (request == null) {
return true;
}
String parameter = request.getParameter("fields");
if (!StringUtils.hasLength(parameter)) {
return true;
}
List<String> fields = Arrays.asList(parameter.split(","));
if (fields == null || fields.isEmpty()) {
return true;
}
String name = writer.getName();
return fields.contains(name);
}
}The filter reads a request parameter named fields, splits it by commas, and only serializes properties whose names appear in that list. If the parameter is missing or empty, all fields are included.
5. (Optional) Extend the filter for permission‑based control . By accessing the property’s declaring class, you can decide whether the current user is allowed to see a particular field:
protected boolean include(PropertyWriter writer) {
AnnotatedMember member = writer.getMember();
if (member == null) {
return true;
}
Class<?> clazz = member.getDeclaringClass();
// custom permission logic based on clazz and user context
return true;
}6. Test the solution with a simple controller:
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping("/{id}")
public User query(@PathVariable Long id) {
return new User(id, "张三", 44, "11111111", "18999999999");
}
}Calling /users/1?fields=id,name returns only the id and name fields, while omitting age, idNo, and phone.
These screenshots illustrate the filtered JSON output and the corresponding request URLs.
In summary, by leveraging Jackson’s mixin and filter mechanisms, you can achieve fine‑grained, request‑driven field selection in Spring Boot APIs without extra DTOs or third‑party query languages, keeping the solution lightweight and easy to maintain.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
