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字段的值:
- 给Email类指定自定义反序列化器:
@JsonDeserialize(using = EmailDeserializer.class) public class Email { @JsonProperty(access = JsonProperty.Access.READ_ONLY) @Email private String mail; // 其他属性及getter/setter }
- 实现反序列化器:
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
相关产品推荐
相关产品推荐

