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

2022-09-07 16:58:45 浏览数 (1)

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

代码语言:javascript复制
public static class JsonTestUser{
		private Integer id;
		private String name;
		/** (JSON格式)扩展字段 */
		private String props;
		......//
}

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

代码语言:javascript复制
{
  "id":0,
  "name":"tom",
  "props":{
    "phone":"13088927898",
    "email":"hello@qq.com"
  }
}

序列化

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

代码语言:javascript复制
@JsonRawValue
private String props;

反序列化

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

代码语言:javascript复制
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 {
    	/**
    	 * 如果希望保存原始字符串内容,空格,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);
    }
}

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

代码语言:javascript复制
@JsonRawValue
@JsonDeserialize(using = RawJsonDeserializer.class)
private String props;

参考资料

Deserializing JSON property as String with Jackson

0 人点赞