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

如何使用JAXB根据条件隐藏Java DTO中的指定字段?

解决方案

首先先修正你DTO里的两个语法错误:

  • Public 应小写为 public
  • protectd 拼写错误,应为 protected

接下来分JSON(以Jackson框架为例)和XML两种场景给出实现方案:

一、JSON 响应(Jackson 框架)

要实现动态字段显示逻辑,最灵活的方式是自定义序列化器,或者使用Jackson的动态过滤规则:

方案1:自定义序列化器

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

import java.io.IOException;

public class OrderSerializer extends StdSerializer<Order> {

    protected OrderSerializer() {
        super(Order.class);
    }

    @Override
    public void serialize(Order order, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStartObject();
        // 固定序列化的字段
        gen.writeNumberField("id", order.id);
        gen.writeStringField("date", order.date);
        gen.writeStringField("market", order.market);
        
        // 按条件处理mart字段
        if ("India".equals(order.market)) {
            // India时不输出mart
        } else if ("Australia".equals(order.market)) {
            // Australia时强制输出,即使为null
            gen.writeStringField("mart", order.mart);
        } else {
            // 其他场景:仅当非null时输出
            if (order.mart != null) {
                gen.writeStringField("mart", order.mart);
            }
        }
        gen.writeEndObject();
    }
}

然后在Order类上标注使用该序列化器:

@XmlRootElement(name = "order1")
@JsonSerialize(using = OrderSerializer.class)
public class Order {

    @XmlElement
    protected long id;
    
    @XmlElement
    protected String date;
    
    @XmlElement
    protected String mart;
    
    @XmlElement
    protected String market;

    // 必须添加getter/setter,Jackson和JAXB都依赖这些方法
    public long getId() { return id; }
    public void setId(long id) { this.id = id; }
    public String getDate() { return date; }
    public void setDate(String date) { this.date = date; }
    public String getMart() { return mart; }
    public void setMart(String mart) { this.mart = mart; }
    public String getMarket() { return market; }
    public void setMarket(String market) { this.market = market; }
}

方案2:使用Jackson动态过滤规则

如果不想编写全量序列化器,可以用@JsonInclude配合自定义过滤器实现:

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;

@XmlRootElement(name = "order1")
@JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = MartFieldFilter.class)
public class Order {
    // 字段定义不变,需添加getter/setter
    
    public static class MartFieldFilter {
        @Override
        public boolean equals(Object obj) {
            Order order = (Order) obj;
            if ("India".equals(order.getMarket())) {
                return true; // 返回true表示过滤(隐藏)mart字段
            } else if ("Australia".equals(order.getMarket())) {
                return false; // 返回false表示强制保留,即使为null
            }
            // 其他场景:仅当mart为null时过滤
            return order.getMart() == null;
        }
    }
}

注意:实际使用时建议实现ContextualFilter来获取当前序列化的上下文,避免上述示例中的类型转换风险。

二、XML 响应(JAXB)

JAXB的动态字段控制可以通过自定义XmlAdapter实现:

方案:自定义XmlAdapter

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class OrderAdapter extends XmlAdapter<OrderAdapter.AdaptedOrder, Order> {

    // 定义适配类,用于控制XML序列化的字段
    public static class AdaptedOrder {
        protected long id;
        protected String date;
        protected String mart;
        protected String market;

        // getter/setter
        public long getId() { return id; }
        public void setId(long id) { this.id = id; }
        public String getDate() { return date; }
        public void setDate(String date) { this.date = date; }
        public String getMart() { return mart; }
        public void setMart(String mart) { this.mart = mart; }
        public String getMarket() { return market; }
        public void setMarket(String market) { this.market = market; }
    }

    @Override
    public AdaptedOrder marshal(Order order) throws Exception {
        AdaptedOrder adapted = new AdaptedOrder();
        adapted.setId(order.getId());
        adapted.setDate(order.getDate());
        adapted.setMarket(order.getMarket());
        
        // 按条件处理mart字段
        if ("India".equals(order.getMarket())) {
            // India时不设置mart,XML不会生成该元素
        } else if ("Australia".equals(order.getMarket())) {
            // Australia时强制设置,即使为null
            adapted.setMart(order.getMart());
        } else {
            // 其他场景仅当非null时设置
            if (order.getMart() != null) {
                adapted.setMart(order.getMart());
            }
        }
        return adapted;
    }

    @Override
    public Order unmarshal(AdaptedOrder adapted) throws Exception {
        // 反序列化逻辑,按需实现
        Order order = new Order();
        order.setId(adapted.getId());
        order.setDate(adapted.getDate());
        order.setMart(adapted.getMart());
        order.setMarket(adapted.getMarket());
        return order;
    }
}

然后在Order类上标注使用该适配器:

@XmlRootElement(name = "order1")
@XmlJavaTypeAdapter(OrderAdapter.class)
public class Order {
    // 字段定义和getter/setter不变
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 18:13:25