Skip to content

Commit

Permalink
add support for JSON.OBJLEN command
Browse files Browse the repository at this point in the history
  • Loading branch information
iamskp11 committed Sep 15, 2024
1 parent 376ff24 commit b2995ed
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 0 deletions.
11 changes: 11 additions & 0 deletions internal/eval/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,16 @@ var (
Eval: evalSELECT,
Arity: 1,
}
jsonobjlenCmdMeta = DiceCmdMeta{
Name: "JSON.OBJLEN",
Info: `JSON.OBJLEN key [path]
Returns the encoded RESP value of the key, if present
Null reply: If the key doesn't exist or has expired.
Error reply: If the number of arguments is incorrect or the stored value is not a JSON type.`,
Eval: evalJSONOBJLEN,
Arity: 2,
KeySpecs: KeySpecs{BeginIndex: 1},
}
)

func init() {
Expand Down Expand Up @@ -759,6 +769,7 @@ func init() {
DiceCmds["JSON.STRLEN"] = jsonStrlenCmdMeta
DiceCmds["HLEN"] = hlenCmdMeta
DiceCmds["SELECT"] = selectCmdMeta
DiceCmds["JSON.OBJLEN"] = jsonobjlenCmdMeta
}

// Function to convert DiceCmdMeta to []interface{}
Expand Down
55 changes: 55 additions & 0 deletions internal/eval/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -2832,3 +2832,58 @@ func evalSELECT(args []string, store *dstore.Store) []byte {

return clientio.RespOK
}


// evalJSONOBJLEN returns the number of fields in a JSON object at a specified path within a Redis JSON document.
// Returns: An integer indicating the number of fields in the JSON object, or an error if the path does not point to an object or the key does not exist.
func evalJSONOBJLEN(args []string, store *dstore.Store) []byte {
if len(args) < 1 {
return diceerrors.NewErrArity("JSON.OBJLEN")
}

key := args[0]
// Default path is root if not specified
path := defaultRootPath
if len(args) > 1 {
path = args[1]
}

// Retrieve the object from the database
// TODO: Check if we should throw error here
obj := store.Get(key)
if obj == nil {
return clientio.RespNIL
}

// Check if the object is of JSON type
errWithMessage := object.AssertTypeAndEncoding(obj.TypeEncoding, object.ObjTypeJSON, object.ObjEncodingJSON)
if errWithMessage != nil {
return errWithMessage
}

jsonData := obj.Value
// If path is root, return length of the entire JSON
if path == defaultRootPath {
jsonObjLen := len(jsonData.(map[string]interface{}))
return clientio.Encode(jsonObjLen, false)
}

// Parse the JSONPath expression
expr, err := jp.ParseString(path)
if err != nil {
return diceerrors.NewErrWithMessage("invalid JSONPath")
}

// Execute the JSONPath query
results := expr.Get(jsonData)
if len(results) == 0 {
return clientio.RespNIL
}

if utils.GetJSONFieldType(results[0]) != utils.ObjectType {
return diceerrors.NewErrWithMessage("the path does not point to a JSON object")
}

jsonObjLen := len(results[0].(map[string]interface{}))
return clientio.Encode(jsonObjLen, false)
}

0 comments on commit b2995ed

Please sign in to comment.