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

如何通过注解或自定义序列化器将JSON键映射为Java对象的name属性

问题描述

我有一段需要序列化和反序列化的JSON数据:

{
  "name1": {
    "key1": "value1",
    "key2": "value2"
  }
}

能否通过注解或自定义(反)序列化器,将JSON中的外层键(例如"name1")作为Java对象的name属性?当前使用的Java代码如下:

@lombok.Data
public class Example {

    private String name;

    private Map<String,String> properties = new HashMap<>();

    public Example(String name) {
        this.name = name;
    }

    public void add(String attr1, String val1) {
        properties.put(attr1, val1);
    }

    public static void main(String[] args) throws JsonProcessingException {
        Example bean = new Example("name1");
        bean.add("key1", "value1");
        bean.add("key2", "value2");

        String result = new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(bean);
        System.out.println(result);
    }
}

未做任何配置时的输出结果为:

{
  "name" : "name1",
  "properties" : {
    "key1" : "value1",
    "key2" : "value2"
  }
}
解决方案

要实现这种动态键与Java对象属性的映射,需为Example类自定义Jackson的序列化器和反序列化器,具体步骤如下:

1. 自定义序列化器

序列化时将name作为外层键,properties作为对应的值,创建ExampleSerializer:

public class ExampleSerializer extends StdSerializer<Example> {

    protected ExampleSerializer() {
        super(Example.class);
    }

    @Override
    public void serialize(Example value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStartObject();
        // 把name设为外层键,properties作为对应值写入
        gen.writeObjectField(value.getName(), value.getProperties());
        gen.writeEndObject();
    }
}

2. 自定义反序列化器

反序列化时读取外层唯一键作为name,键对应的值解析为properties,创建ExampleDeserializer:

public class ExampleDeserializer extends StdDeserializer<Example> {

    protected ExampleDeserializer() {
        super(Example.class);
    }

    @Override
    public Example deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode node = p.getCodec().readTree(p);
        // 获取外层唯一键作为name属性值
        String name = node.fieldNames().next();
        JsonNode propertiesNode = node.get(name);
        // 解析内层键值对到properties Map
        Map<String, String> properties = new HashMap<>();
        propertiesNode.fieldNames().forEachRemaining(key -> {
            properties.put(key, propertiesNode.get(key).asText());
        });
        Example example = new Example(name);
        example.setProperties(properties);
        return example;
    }
}

3. 为Example类绑定(反)序列化器

在Example类上添加@JsonSerialize和@JsonDeserialize注解,指定自定义的序列化器和反序列化器:

@lombok.Data
@JsonSerialize(using = ExampleSerializer.class)
@JsonDeserialize(using = ExampleDeserializer.class)
public class Example {

    private String name;

    private Map<String,String> properties = new HashMap<>();

    public Example(String name) {
        this.name = name;
    }

    public void add(String attr1, String val1) {
        properties.put(attr1, val1);
    }

    public static void main(String[] args) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        // 序列化测试
        Example bean = new Example("name1");
        bean.add("key1", "value1");
        bean.add("key2", "value2");
        String result = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(bean);
        System.out.println("序列化结果:");
        System.out.println(result);

        // 反序列化测试
        String json = "{\"name1\":{\"key1\":\"value1\",\"key2\":\"value2\"}}";
        Example deserializedBean = mapper.readValue(json, Example.class);
        System.out.println("\n反序列化结果:");
        System.out.println("name: " + deserializedBean.getName());
        System.out.println("properties: " + deserializedBean.getProperties());
    }
}

运行效果

执行main方法后,序列化输出与目标JSON结构一致:

{
  "name1" : {
    "key1" : "value1",
    "key2" : "value2"
  }
}

反序列化后能正确还原对象属性:

反序列化结果:
name: name1
properties: {key1=value1, key2=value2}

内容的提问来源于stack exchange,提问作者János Balázs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 18:27:52