Configure a custom fastJson serialization tool class for Redis

alibaba.fastjson has provided a tool class GenericFastJsonRedisSerializer for serializing Redis storage objects, but the tool returns to Object when deserializing. We define an extended tool class based on GenericFastJsonRedisSerializer, and automatically convert it to the specified java Object after deserializing.

  • GenericFastJsonRedisSerializer source code
package com.alibaba.fastjson.support.spring;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.util.IOUtils;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;

/**
 * {@link RedisSerializer} FastJson Generic Impl
 * @author lihengming
 * @since 1.2.36
 */
public class GenericFastJsonRedisSerializer implements RedisSerializer<Object> {
    private final static ParserConfig defaultRedisConfig = new ParserConfig();
    static { defaultRedisConfig.setAutoTypeSupport(true);}

    public byte[] serialize(Object object) throws SerializationException {
        if (object == null) {
            return new byte[0];
        }
        try {
            return JSON.toJSONBytes(object, SerializerFeature.WriteClassName);
        } catch (Exception ex) {
            throw new SerializationException("Could not serialize: " + ex.getMessage(), ex);
        }
    }

    public Object deserialize(byte[] bytes) throws SerializationException {
        if (bytes == null || bytes.length == 0) {
            return null;
        }
        try {
            return JSON.parseObject(new String(bytes, IOUtils.UTF8), Object.class, defaultRedisConfig);
        } catch (Exception ex) {
            throw new SerializationException("Could not deserialize: " + ex.getMessage(), ex);
        }
    }
}

  • Customize FastJsonRedisSerializer
import java.nio.charset.Charset;

import com.alibaba.fastjson.parser.ParserConfig;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

/**
 * <Description> fastjson Serialization < br >
 * 
 * @author xubin<br>
 * @version 1.0<br>
 * @taskId <br>
 * @param <T> generalization
 * @CreateDate Nov 8, 2018 <br>
 */

public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {

    private final static ParserConfig defaultRedisConfig = new ParserConfig();
    static { defaultRedisConfig.setAutoTypeSupport(true);}

    /**
     * DEFAULT_CHARSET <br>
     */
    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    /**
     * clazz Deserialize class < br >
     */
    private Class<T> clazz;

    /**
     * <Description> Constructor < br >
     * 
     * @param clazz Deserialize target class
     */
    public FastJsonRedisSerializer(Class<T> clazz) {
        super();
        this.clazz = clazz;
    }

    /**
     * Description: Serialization < br >
     * 
     * @author xubin<br>
     * @taskId <br>
     * @param t
     * @return
     * @throws SerializationException <br>
     */
    @Override
    public byte[] serialize(T t) throws SerializationException {
        if (t == null) {
            return new byte[0];
        }
        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }


    /**
     * Description: Deserialization < br >
     * 
     * @author xubin<br>
     * @taskId <br>
     * @param bytes
     * @return
     * @throws SerializationException <br>
     */
    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (bytes == null || bytes.length <= 0) {
            return null;
        }
        String str = new String(bytes, DEFAULT_CHARSET);
        return (T) JSON.parseObject(str, clazz, defaultRedisConfig);
    }

}

  • json message example
{
    "@type": "com.lucas.device.mqtt.protocol.MqttPacketCache",
    "id": 647682641483370500,
    "packet": {
        "@type": "com.lucas.device.mqtt.protocol.Packet",
        "body": {
            "@type": "com.lucas.device.mqtt.protocol.payload.BindFacesetBody",
            "facesetTokenList": [
                "630281772974575616"
            ]
        },
        "head": {
            "code": 114,
            "id": 647682641483370500,
            "type": 2,
            "version": 1
        }
    }
}

Note here is defaultRedisConfig.setAutoTypeSupport(true). When calling JSON.toJSONString(object, SerializerFeature.WriteClassName), it will contain @ type information in JSON message. When deserializing, it will be based on @type Check the object to be mapped, so make sure that the type to be deserialized has a default constructor and the serialization tool opens the support of autoType, otherwise the deserialization will encounter the exception com.alibaba.fastjson.JSONException: autoType is not support.

  • RedisConfig configures a custom serialization tool class
   /**
     * Description: <br>
     * 
     * @author xubin<br>
     * @taskId <br>
     * @param factory Factory object
     * @return <br>
     */
    @Bean
    public RedisTemplate<String, MqttPacketCache> packetRedisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, MqttPacketCache> redisTemplate = new RedisTemplate<>();
        StringRedisSerializer stringSerializer = new StringRedisSerializer();
        redisTemplate.setConnectionFactory(factory);
        redisTemplate.setKeySerializer(stringSerializer);
        redisTemplate.setValueSerializer(new FastJsonRedisSerializer<>(MqttPacketCache.class));
        redisTemplate.setHashKeySerializer(stringSerializer);
        redisTemplate.setHashValueSerializer(new FastJsonRedisSerializer<>(MqttPacketCache.class));
        return redisTemplate;
    }

Tags: Programming JSON Redis Java Spring

Posted on Wed, 06 Nov 2019 16:58:51 -0500 by MsShelle