Как десериализовать строку в объект Java - PullRequest
0 голосов
/ 22 мая 2018

Я пытаюсь десериализовать String в Java Object с сервера Redis, который используется для хранения сеансов Spring, и я хочу десериализовать его вне среды Spring.Я думаю, что сериализатор Spring Redis, вероятно, использует набор символов по умолчанию, UTF-8, для сериализации Java Object в строку.

Строка в Redis:

\ 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

Метод, который я использую:

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, вероятно, там, где проблема, но я все еще хочу спросить, знает ли кто-нибудь, как решить эту проблему безизменение части сериализации.

1 Ответ

0 голосов
/ 22 мая 2018

Я бы посоветовал вам разобрать строку самостоятельно.Похоже, это простая последовательность экранированных и неэкранированных байтов.

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);
}
...