如何使用JAXB根据条件隐藏Java DTO中的指定字段?
解决方案
首先先修正你DTO里的两个语法错误:
Public应小写为publicprotectd拼写错误,应为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
相关产品推荐
相关产品推荐

