1

I want to store Java data structures in Redis. I wrote code in Java as below:

public static void main(String[] args) throws IOException {
    Map<String, String> map = new HashMap<String, String>();
    map.put("foo", "1");
    map.put("bar", "2");
    map.put("baz", "3");
    ArrayList<String> list = new ArrayList<String>();
    list.add("foo");
    list.add("bar");
    MessagePack mp = new MessagePack();
    byte[] serializedMap = mp.write(map);
    byte[] serializedList = mp.write(list);
    Jedis jedis = new Jedis("localhost");
    jedis.zadd("test".getBytes(), 1000, serializedMap);
    jedis.zadd("test2".getBytes(), 1000, serializedList);
    jedis.close();
}

I have no problem with deserializing in Redis value (serializedList) of "test2":

eval "local r = redis.call('zrange', 'test2', 0, 1); return cmsgpack.unpack(r[1]);" 0
1) "foo"
2) "bar"

Unfortunately, I can't deal with serializedMap. I tried, with no luck, something like this:

eval "local r = redis.call('zrange', 'test', 0, 1); return cmsgpack.unpack(r[1]);" 0
(empty list or set)

Can anybody give me a hint how to do that correctly?

kaz3t
  • 61
  • 6

1 Answers1

1

Please refer to the section Conversion between Lua and Redis data types of the Redis EVAL documentation. As you can see Lua to Redis conversion rules only handle:

  • Lua table (array) = sequence,
  • Lua table with a single ok field,
  • Lua table with a single err field.

This is why a generic map is not handled (it is truncated to the first nil inside the Lua array if any):

$ redis-cli
> eval 'return cmsgpack.pack{foo="1", bar="2", baz="3"}' 0
"\x83\xa3baz\xa13\xa3bar\xa12\xa3foo\xa11"
> eval 'return cmsgpack.unpack(ARGV[1])' 0 "\x83\xa3baz\xa13\xa3bar\xa12\xa3foo\xa11"
(empty list or set)

Note: see also this answer for more details.

Community
  • 1
  • 1
deltheil
  • 15,496
  • 2
  • 44
  • 64