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.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
The Simplest Solution for Dynamic Fields in Spring Boot APIs

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Spring BootREST APIJacksonMixinDynamic FieldsJsonFilter
Spring Full-Stack Practical Cases
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.