You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中如何为ArrayList的每个元素应用不同的JsonView?

为列表元素动态应用不同JsonView的解决方案

1. 定义视图标记接口

先创建两个空接口,用来标记不同的序列化视图场景:

public class EmpViews {
    // 标记包含age字段的视图
    public interface WithAge {}
    // 标记不包含age字段的视图
    public interface WithoutAge {}
}

2. 给Emp类属性绑定视图

在Emp类的属性上用@JsonView注解,指定每个属性允许被哪些视图序列化:

public class Emp {
    // 两个视图都能序列化id
    @JsonView({EmpViews.WithAge.class, EmpViews.WithoutAge.class})
    private Long id;
    
    // 两个视图都能序列化name
    @JsonView({EmpViews.WithAge.class, EmpViews.WithoutAge.class})
    private String name;
    
    // 仅WithAge视图能序列化age
    @JsonView(EmpViews.WithAge.class)
    private Integer age;

    // 构造方法、getter/setter省略
}

3. 自定义序列化器实现动态视图切换

Spring默认的@JsonView只能给整个请求响应指定单一视图,要实现每个元素不同视图,需要自定义序列化逻辑:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.IOException;

public class DynamicEmpSerializer extends JsonSerializer<Emp> {
    private final JsonMapper mapper = new JsonMapper();

    @Override
    public void serialize(Emp emp, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        ObjectNode node = mapper.valueToTree(emp);
        // 这里可自定义判断条件,示例中以id=1作为包含age的标记
        if (!emp.getId().equals(1L)) {
            node.remove("age");
        }
        gen.writeTree(node);
    }
}

4. 在Controller中应用自定义序列化器

有两种方式可以生效:

方式一:全局注册(所有Emp对象都适用)

在配置类中注册序列化器:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;

@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(Emp.class, new DynamicEmpSerializer());
        mapper.registerModule(module);
        return mapper;
    }
}

之后Controller直接返回列表即可:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;

@RestController
public class EmpController {
    @GetMapping("/emps")
    public List<Emp> getEmps() {
        Emp emp1 = new Emp(1L, "张三", 25);
        Emp emp2 = new Emp(2L, "李四", 30);
        Emp emp3 = new Emp(3L, "王五", 28);
        return List.of(emp1, emp2, emp3);
    }
}

方式二:局部使用(仅当前接口生效)

在Controller的返回列表上标注@JsonSerialize指定序列化器:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.util.List;

@RestController
public class EmpController {
    @GetMapping("/emps")
    @JsonSerialize(contentUsing = DynamicEmpSerializer.class)
    public List<Emp> getEmps() {
        Emp emp1 = new Emp(1L, "张三", 25);
        Emp emp2 = new Emp(2L, "李四", 30);
        Emp emp3 = new Emp(3L, "王五", 28);
        return List.of(emp1, emp2, emp3);
    }
}

5. 可选方案:手动构建响应节点

如果不想自定义序列化器,也可以手动构造每个元素的JSON节点,再组成数组返回:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;

@RestController
public class EmpController {
    private final ObjectMapper objectMapper;

    public EmpController(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @GetMapping("/emps")
    public ArrayNode getEmps() {
        ArrayNode arrayNode = objectMapper.createArrayNode();
        
        Emp emp1 = new Emp(1L, "张三", 25);
        ObjectNode node1 = objectMapper.valueToTree(emp1);
        arrayNode.add(node1);
        
        Emp emp2 = new Emp(2L, "李四", 30);
        ObjectNode node2 = objectMapper.valueToTree(emp2);
        node2.remove("age");
        arrayNode.add(node2);
        
        Emp emp3 = new Emp(3L, "王五", 28);
        ObjectNode node3 = objectMapper.valueToTree(emp3);
        node3.remove("age");
        arrayNode.add(node3);
        
        return arrayNode;
    }
}

内容的提问来源于stack exchange,提问作者Kundan Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 02:05:16