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

如何基于Type字段值动态设置Jackson序列化的属性名?

动态根据Type字段调整JSON属性名的解决方案

不用创建十多个子类,直接利用Jackson的自定义序列化逻辑就能实现需求,以下是两种实用方案:

方案一:自定义全量序列化器

直接为Data类编写序列化器,手动控制每个字段的输出键名:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;

public class DataSerializer extends JsonSerializer<Data> {
    @Override
    public void serialize(Data data, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeStartObject();
        // 根据type动态选择surname的JSON键名
        String surnameKey = data.getType() == Type.PERSON ? "name" : "username";
        gen.writeStringField(surnameKey, data.getSurname());
        // 输出type字段
        gen.writeStringField("type", data.getType().name());
        // 如果有其他字段,在这里按同样方式添加
        gen.writeEndObject();
    }
}

然后在Data类上添加注解指定序列化器:

import com.fasterxml.jackson.databind.annotation.JsonSerialize;

@JsonSerialize(using = DataSerializer.class)
class Data {
    @JsonAlias({"username", "name"})
    String surname;
    Type type;

    // 必须添加getter方法,序列化器需要访问字段值
    public String getSurname() {
        return surname;
    }

    public Type getType() {
        return type;
    }

    // 可选:添加setter和构造方法
}

enum Type{
    PERSON, USER
}

方案二:使用BeanSerializerModifier修改单个字段

如果Data类有很多其他字段,不想手动写全量序列化逻辑,可以用BeanSerializerModifier单独修改surname字段的序列化行为:

1. 编写Modifier类

import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import java.util.List;

public class DataBeanSerializerModifier extends BeanSerializerModifier {
    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
        for (BeanPropertyWriter writer : beanProperties) {
            if ("surname".equals(writer.getName())) {
                // 为surname字段指定自定义序列化逻辑
                writer.assignSerializer(new JsonSerializer<String>() {
                    @Override
                    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                        // 获取当前序列化的Data对象
                        Data currentData = (Data) gen.getCurrentValue();
                        String targetKey = currentData.getType() == Type.PERSON ? "name" : "username";
                        gen.writeStringField(targetKey, value);
                    }
                });
                // 移除原有的字段writer,避免重复输出
                beanProperties.remove(writer);
                break;
            }
        }
        return beanProperties;
    }
}

2. 注册到ObjectMapper

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;

ObjectMapper mapper = new ObjectMapper();
SimpleModule customModule = new SimpleModule();
customModule.setSerializerModifier(new DataBeanSerializerModifier());
mapper.registerModule(customModule);

方案对比

  • 方案一:代码简洁直接,适合字段较少的Data类,但如果后续新增字段,需要手动在序列化器中添加输出逻辑。
  • 方案二:只修改目标字段的行为,保留其他字段的默认序列化逻辑,扩展性更强,适合字段较多的场景。

如果需要反序列化(JSON转Data对象),可以结合@JsonAlias注解,或者编写对应的自定义反序列化器,逻辑和序列化类似,根据JSON中的键名动态赋值给surname字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 03:35:24