【问题标题】:How to Deserialize String to Java Object如何将字符串反序列化为 Java 对象
【发布时间】:2018-11-01 13:53:20
【问题描述】:

我尝试从用于存储 Spring 会话的 Redis 服务器将字符串反序列化为 Java 对象,并且我想在 Spring 框架之外对其进行反序列化。我认为 Spring Redis 序列化程序可能使用默认字符集 UTF-8 将 Java 对象序列化为字符串。

Redis 中的字符串:

\xAC\xED\x00\x05sr\x00\x0Ejava.lang.Long;\x8B\xE4\x90\xCC\x8F#\xDF\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang。编号\x86\xAC\x95\x1D\x0B\x94\xE0\x8B\x02\x00\x00xp\x00\x00\x00\x00\x00\x00\xD7

我使用的方法:

private static void scanKeys(Jedis jedis, String prefix, String hashKey)
        throws IOException, ClassNotFoundException {
    Set<String> keys = jedis.keys(prefix + "*");

    for (String key : keys) {
        if (!key.contains("expir")) {
            Map<String, String> sessionMap = jedis.hgetAll(key);

            for (Entry<String, String> entry : sessionMap.entrySet()) {

                if (entry.getValue() != null && entry.getKey().equals(hashKey)) {
                    System.out.println(entry.getKey());
                    System.out.println(entry.getValue());

                    byte[] output = entry.getValue().getBytes(charset);
                    System.out.println(Arrays.toString(output));    
                    try {
                        Long id = (Long) deserialize(output);
                        System.out.println(id);
                    } catch (EOFException e) {
                        break;
                    }
                }
            }

        }

    }
}

public static Object deserialize(byte[] data) throws IOException, ClassNotFoundException {
    ByteArrayInputStream in = new ByteArrayInputStream(data);
    ObjectInputStream is = new ObjectInputStream(in);
    return is.readObject();
}

错误信息:

java.io.StreamCorruptedException: invalid stream header: EFBFBDEF
    at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:862)
    at java.io.ObjectInputStream.<init>(ObjectInputStream.java:354)
    at practice.redis.jedis.App.deserialize(App.java:191)
    at practice.redis.jedis.App.scanKeys(App.java:168)
    at practice.redis.jedis.App.main(App.java:77)

我知道用UTF-8转换byte[]和String之间的转换可能是问题所在,但我还是想问一下有没有人知道如何在不修改序列化部分的情况下解决这个问题。

【问题讨论】:

    标签: java utf-8 redis deserialization spring-data-redis


    【解决方案1】:

    我建议你自己解析字符串。看起来它是一个简单的转义和非转义字节序列。

    String value = "\\xAC\\xED\\x00\\x05sr\\x00\\x0Ejava.lang.Long;\\x8B\\xE4\\x90\\xCC\\x8F#\\xDF\\x02\\x00\\x01J\\x00\\x05valuexr\\x00\\x10java.lang.Number\\x86\\xAC\\x95\\x1D\\x0B\\x94\\xE0\\x8B\\x02\\x00\\x00xp\\x00\\x00\\x00\\x00\\x00\\x00\\xD7";
    
    try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
        int i = 0;
        while (i < value.length()) {
            char ch = value.charAt(i);
            if (ch == '\\') {
                if (value.charAt(i + 1) != 'x') {
                    throw new UnsupportedOperationException();
                }
                String hex = value.substring(i + 2, i + 4);
                byteArrayOutputStream.write(Integer.parseInt(hex, 16) & 0xFF);
                i += 4;
            } else {
                byteArrayOutputStream.write(ch);
                i++;
            }
        }
    
        byte[] output = byteArrayOutputStream.toByteArray();
        Long id = (Long) deserialize(output);
        System.out.println(id);
    }
    

    【讨论】:

    • 如果我直接从 Redis 获取值,它会抛出 UnsupportedOperationException。
    • 当我出于某些原因使用您的解决方案时,它会抛出 java.io.EOFException。
    猜你喜欢
    • 2020-02-03
    • 1970-01-01
    • 2022-11-15
    • 1970-01-01
    • 2020-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多