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

Spring 1.4.5中Jackson只读属性如何接收同名JSON字段?

解决Spring 1.4.5中READ_ONLY属性接收JSON字段的问题

方案一:使用@JsonAlias新增接收字段

给新增属性添加@JsonAlias注解,该注解仅在反序列化时生效,不会和原有mail字段的序列化逻辑冲突:

public class Email {
    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    @Email
    private String mail;

    // 仅用于接收JSON中的mail字段,序列化时不输出
    @JsonAlias("mail")
    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private String from;

    // 可添加getter方法获取from的值
    public String getFrom() {
        return from;
    }
}

Jackson会自动将JSON里的mail字段映射到from属性,原有mail字段的READ_ONLY标记保持不变,不影响生产环境的序列化行为。

方案二:自定义Jackson反序列化器

通过自定义反序列化器绕开READ_ONLY限制,手动设置mail字段的值:

  1. 给Email类指定自定义反序列化器:
@JsonDeserialize(using = EmailDeserializer.class)
public class Email {
    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    @Email
    private String mail;

    // 其他属性及getter/setter
}
  1. 实现反序列化器:
public class EmailDeserializer extends StdDeserializer<Email> {
    public EmailDeserializer() {
        super(Email.class);
    }

    @Override
    public Email deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode root = p.getCodec().readTree(p);
        Email email = new Email();

        // 手动读取mail字段并赋值
        if (root.has("mail")) {
            String mailVal = root.get("mail").asText();
            try {
                Field mailField = Email.class.getDeclaredField("mail");
                mailField.setAccessible(true);
                mailField.set(email, mailVal);
            } catch (ReflectiveOperationException e) {
                throw new IOException("Failed to inject mail value", e);
            }
        }

        // 复用默认逻辑反序列化其他属性
        JsonParser subParser = root.traverse(p.getCodec());
        subParser.nextToken();
        Email defaultEmail = ctxt.readValue(subParser, Email.class);
        BeanUtils.copyProperties(defaultEmail, email);

        return email;
    }
}

该方案完全保留原有mail字段的READ_ONLY标记,仅在反序列化阶段手动注入值,不影响原有序列化输出。

方案三:Controller层直接解析原始JSON

在Controller中接收原始JSON字符串,解析出mail值后再映射为Email对象:

@PostMapping(value = ENDPOINT, consumes= "application/json")
public ResponseEntity<?> post(@RequestBody String rawJson) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    JsonNode jsonNode = mapper.readTree(rawJson);
    String mailVal = jsonNode.get("mail").asText();

    // 反序列化为Email对象
    Email email = mapper.readValue(rawJson, Email.class);

    // 通过反射将mailVal注入到email对象
    try {
        Field mailField = Email.class.getDeclaredField("mail");
        mailField.setAccessible(true);
        mailField.set(email, mailVal);
    } catch (ReflectiveOperationException e) {
        // 异常处理逻辑
    }

    // 后续业务处理
    return ResponseEntity.ok().build();
}

此方案无需修改实体类,直接在Controller层完成字段解析和注入,适合快速应急场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 23:32:45