Skip to content

Commit 2e027c0

Browse files
committed
feat: add JSON DUMP/RESTORE support via type coercion to String
- Map JSON type to RDBTypeString (type 0) for Redis compatibility - Serialize JSON to string representation during DUMP - RESTORE creates String type (similar to SortedInt → Set pattern) - Add TestDump_JSON following existing test patterns - Type changes: ReJSON-RL → string after RESTORE (trade-off for compatibility)
1 parent a10b6e1 commit 2e027c0

2 files changed

Lines changed: 45 additions & 1 deletion

File tree

src/storage/rdb/rdb.cc

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "types/redis_bitmap.h"
3636
#include "types/redis_bitmap_string.h"
3737
#include "types/redis_hash.h"
38+
#include "types/redis_json.h"
3839
#include "types/redis_list.h"
3940
#include "types/redis_set.h"
4041
#include "types/redis_sortedint.h"
@@ -723,7 +724,7 @@ Status RDB::Dump(const std::string &key, const RedisType type) {
723724

724725
Status RDB::SaveObjectType(const RedisType type) {
725726
int robj_type = -1;
726-
if (type == kRedisString || type == kRedisBitmap) {
727+
if (type == kRedisString || type == kRedisBitmap || type == kRedisJson) {
727728
robj_type = RDBTypeString;
728729
} else if (type == kRedisHash) {
729730
robj_type = RDBTypeHash;
@@ -798,6 +799,20 @@ Status RDB::SaveObject(const std::string &key, const RedisType type) {
798799
return {Status::RedisExecErr, s.ToString()};
799800
}
800801
return SaveStringObject(value);
802+
} else if (type == kRedisJson) {
803+
redis::Json json_db(storage_, ns_);
804+
JsonValue value;
805+
auto s = json_db.Get(ctx, key, {}, &value);
806+
if (!s.ok() && !s.IsNotFound()) {
807+
return {Status::RedisExecErr, s.ToString()};
808+
}
809+
std::string json_str;
810+
Config *config = storage_->GetConfig();
811+
auto dump_status = value.Dump(&json_str, config->json_max_nesting_depth);
812+
if (!dump_status.IsOK()) {
813+
return {Status::RedisExecErr, dump_status.Msg()};
814+
}
815+
return SaveStringObject(json_str);
801816
} else if (type == kRedisSortedint) {
802817
redis::Sortedint sortedint_db(storage_, ns_);
803818
std::vector<uint64_t> ids;

tests/gocase/unit/dump/dump_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,3 +220,32 @@ func TestDump_SortedInt(t *testing.T) {
220220
expectedMembers := []string{"5", "12", "23", "89", "100"}
221221
require.ElementsMatch(t, expectedMembers, members)
222222
}
223+
224+
func TestDump_JSON(t *testing.T) {
225+
srv := util.StartServer(t, map[string]string{})
226+
defer srv.Close()
227+
228+
ctx := context.Background()
229+
rdb := srv.NewClient()
230+
defer func() { require.NoError(t, rdb.Close()) }()
231+
232+
key := "test_json_key"
233+
234+
jsonData := `{"name":"Alice","age":30,"city":"NYC"}`
235+
require.NoError(t, rdb.Do(ctx, "JSON.SET", key, "$", jsonData).Err())
236+
237+
require.EqualValues(t, "ReJSON-RL", rdb.Type(ctx, key).Val())
238+
239+
serialized, err := rdb.Dump(ctx, key).Result()
240+
require.NoError(t, err)
241+
242+
restoredKey := fmt.Sprintf("restore_%s", key)
243+
require.NoError(t, rdb.RestoreReplace(ctx, restoredKey, 0, serialized).Err())
244+
245+
require.EqualValues(t, "string", rdb.Type(ctx, restoredKey).Val())
246+
247+
content := rdb.Get(ctx, restoredKey).Val()
248+
require.Contains(t, content, "Alice")
249+
require.Contains(t, content, "30")
250+
require.Contains(t, content, "NYC")
251+
}

0 commit comments

Comments
 (0)