Skip to content

Java 反序列化在 C# 中保存到 Redis 的数据

🏷️ Java C#

因为两个项目共用的 Redis 缓存,获取在 C# 中保存的数据时反序列化出错。C# 中保存的获取的数据取出来后如下:

js
{"Guid":"ee7a6e30cf98497b9906e25790b03485","Serial":300,"CreateDate":"\/Date(1423292741000-0000)\/","IsOpen":false}

Guid 中没有中间的横线 -,日期类型的格式也比较奇怪。于是使用 Jackson 的自定义序列化及反序列化,使 Java 和 C# 保存到 Redis 中的数据保持一致。

Guid 的反序列化类 (GuidDeserializer)

java
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;

import java.io.IOException;

/**
 * Created by liujiajia on 2017/2/20.
 */
public class GuidDeserializer extends JsonDeserializer {
    @Override
    public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        byte[] newGuid = new byte[36];
        byte[] oldGuid = jsonParser.getText().getBytes();

        int j = 0;
        for (int i = 0; i < newGuid.length; i++) {
            if (i == 8 || i == 13 || i == 18 || i == 23) {
                newGuid[i] = '-';
            } else {
                newGuid[i] = oldGuid[j];
                j++;
            }
        }

        return new String(newGuid);
    }
}

日期类型的反序列化类 (DateDeserializer)

java
import org.apache.commons.httpclient.util.DateUtil;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by liujiajia on 2017/2/20.
 */
public class DateDeserializer extends JsonDeserializer {
    @Override
    public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        String strDate = jsonParser.getText();
        Pattern p = Pattern.compile("\\/Date\\((\\d{13})-(\\d{4})\\)\\/");
        Matcher m = p.matcher(strDate);
        while (m.find()) {
            Date date = new Date(Long.parseLong(m.group(1)));
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
            return sdf.format(date);
        }

        return strDate;
    }
}

Guid 序列化的类 (GuidNoBarSerializer)

java
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;

import java.io.IOException;

/**
 * Created by liujiajia on 2017/2/20.
 */
public class GuidNoBarSerializer extends JsonSerializer {
    @Override
    public void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
        jsonGenerator.writeString(s.toLowerCase().replace("-", ""));
    }
}

日期类型的序列化类 (DateSerializer)

java
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;

import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;

/**
 * Created by liujiajia on 2017/2/20.
 */
public class DateSerializer extends JsonSerializer {
    @Override
    public void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
        try {
            Date date = DateFormat.getDateTimeInstance().parse(s);
            jsonGenerator.writeString("/Date(" + String.valueOf(date.getTime()) + "-0000)/");
        } catch (ParseException e) {
            jsonGenerator.writeString(s);
        }
    }
}

模型中使用上面的自定义标注 (因为 java 中的字段一般是小写开头的, 所以还要加上 JsonProperty 标注, 使字段名和 C# 中的属性名匹配):

java
/**
 * ID
 */
@JsonProperty("Guid")
@JsonSerialize(using = GuidNoBarSerializer.class)
@JsonDeserialize(using = GuidDeserializer.class)
private String guid;

/**
 * 创建时间
 */
@JsonProperty("CreateDate")
@JsonSerialize(using = DateSerializer.class)
@JsonDeserialize(using = DateDeserializer.class)
private String createDate;

从 Redis 中获取时的代码:

java
public static boolean setJsonObjectKey(String key, Object value) {
    try (Jedis jedis = getRedisUtils().getMasterJedisPool().getResource())
    {
        jedis.set(key, new ObjectMapper().writeValueAsString(value));
        jedis.expire(key.getBytes(), _default_expire_secondes);
        return true;
    } catch (Exception ex) {
        return false;
    }
}

public static  T getJsonObjectValue(String key, Class clazz) {
    try (Jedis jedis = getRedisUtils().getSlaveJedisPool().getResource())
    {
        String json = jedis.get(key);
        return new ObjectMapper().readValue(json, clazz);
    } catch (Exception ex) {
        return null;
    }
}

public static  T getJsonObjectValue(String key, TypeReference valueTypeRef) {
    try (Jedis jedis = getRedisUtils().getSlaveJedisPool().getResource())
    {
        String json = jedis.get(key);
        return new ObjectMapper().readValue(json, valueTypeRef);
    } catch (Exception ex) {
        return null;
    }
}