spring/jackson:实现对保存JSON字符串的字段自动序列化和反序列化

对于spring-web项目,在数据库设计时,当我们想增加一个字段时,并不希望修改表结构,希望设计一个专用的扩展字段,将增加的扩展字段以一个JSON字符串形式保存在这个专用字段中。
spring对JSON的序列化和反序列化是依赖jackson来完成的。
数据发送给前端的时候,我们希望jackson在序列化一个数据库记录对象时以JSON的形式返回这个JSON扩展字段的内容,而不是一个String,
同时前端也能以一个JSON的形式定义这个JSON扩展字段,服务端在收到请求jackson在反序列化时能自动将这个JSON字段反序列化为String.这样省去了手工写代码转换的过程才是最方便的。
举例说明一下吧,以下是一个数据库记录对象,props字段为一个JSON扩展字段可以存储任意字段数据

public static class JsonTestUser{
		private Integer id;
		private String name;
		/** (JSON格式)扩展字段 */
		private String props;
		......//
}

我们希望它序列化时,将props字段以原始内容输出,也就是一个JSON对象,而不这种带转义符的字符串:{\"phone\":\"13088927898\","email":\"hello@qq.com\"}

{
  "id":0,
  "name":"tom",
  "props":{
    "phone":"13088927898",
    "email":"hello@qq.com"
  }
}

序列化

将上面的JsonTestUser#props以原始内容输出,并不复杂,利用jackson的注解@JsonRawValue注解就可以完美支持,
如下在props字段定义上增加@JsonRawValue注解,在序列化props字段时就会不加转义符直接原内容输出。

@JsonRawValue
private String props;

反序列化

如果希望将JSON对象反序列化保存到String字段,就需要自己实现一个JsonDeserializer
代码如下:

import java.io.IOException;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
/**
 * Deserializing JSON property as String with Jackson<br>
 * 实现将有{@link com.fasterxml.jackson.annotation.JsonRawValue}注解的
 * 内容为JSON的String类型字段反序列化为String的反序列化器实现
 * copy from <a ref="https://cassiomolin.com/2017/01/24/deserializing-json-property-as-string-with-jackson/">《Deserializing JSON property as String with Jackson》</a>
 *
 */
public class RawJsonDeserializer extends JsonDeserializer<String> {

    @Override
    public String deserialize(JsonParser jp, DeserializationContext ctxt)
           throws IOException, JsonProcessingException {
        /*
         * [实现方案一][推荐]
         * 输入的JSON字符串解析为JSON对象(JsonNode),再输出为JSON字符串,
         * 相当于对JSON字符串进行了格式化
         */
        ObjectMapper mapper = (ObjectMapper) jp.getCodec();
        JsonNode node = mapper.readTree(jp);
        return mapper.writeValueAsString(node);
    	/**
    	 * [实现方案二]
    	 * 如果希望保存原始字符串内容,空格,tab,换行,则采用如下方式,不解析为JSON对象直接将原字符串返回
    	 */
        //long begin = jp.getCurrentLocation().getCharOffset();
        //jp.skipChildren();
        //long end = jp.getCurrentLocation().getCharOffset();

        //String json = jp.getCurrentLocation().getSourceRef().toString();
        //return json.substring((int) begin - 1, (int) end);
    }
}

上面的反序列化器(JsonDeserializer)实现代码中提供了两种实现方案,
区别就是方案一对输入的JSON字段进行了解析,再输出为JSON字符串,输出的数据是格式化过的,原始内容中的空格,制表符(TAB),换行都会被清除掉。推荐使用此方案
方案二则相反,不会对输入JSON字段进行解析,直接输出原始的JSON字符串。

然后再使用@JsonDeserialize注解指定props字段使用我们定义的反序列化器.
如下,就可以完美实现JSON字段的自动序列化和反序列化

@JsonRawValue
@JsonDeserialize(using = RawJsonDeserializer.class)
private String props;

参考资料

《Deserializing JSON property as String with Jackson》

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring Boot中,可以使用Jackson库来实现动态修改字段名的序列化。 首先,确保你的项目已经引入了Jackson库的依赖。在Maven项目中,可以在`pom.xml`文件中添加以下依赖: ```xml <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> ``` 接下来,你可以使用`@JsonAlias`注解来指定字段的别名。例如,假设你有一个Java类如下: ```java public class User { @JsonAlias({"name", "userName"}) private String username; // getters and setters } ``` 在上面的例子中,`username`字段可以通过两个别名`name`和`userName`进行序列化反序列化。 现在,当你将`User`对象序列化JSON字符串时,Jackson会根据字段的别名进行处理。例如: ```java User user = new User(); user.setUsername("John"); ObjectMapper objectMapper = new ObjectMapper(); String json = objectMapper.writeValueAsString(user); System.out.println(json); ``` 输出的JSON字符串将包含别名`name`和`userName`: ```json { "name" : "John" } ``` 同样,当你将JSON字符串反序列化为`User`对象时,Jackson也会根据别名进行匹配。例如: ```java String json = "{\"userName\":\"John\"}"; User user = objectMapper.readValue(json, User.class); System.out.println(user.getUsername()); ``` 输出将是`John`。 这样,你就可以通过使用`@JsonAlias`注解来实现Spring Boot中动态修改字段名的序列化反序列化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

10km

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值