Skip to content

Commit db309cf

Browse files
nic-gibsonofekshenawa
authored andcommitted
Ensure that JSON.GET returns Nil response
Updated JSONCmd.readReply to return redis.Nil if no results. Added a doc line for Val() and Expanded() methods of JSONCmd. Added a test case for non existent keys in json_test.go. Original-PR: #2987
1 parent c592059 commit db309cf

File tree

2 files changed

+57
-5
lines changed

2 files changed

+57
-5
lines changed

json.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,14 @@ func (cmd *JSONCmd) Expanded() (interface{}, error) {
114114
}
115115

116116
func (cmd *JSONCmd) readReply(rd *proto.Reader) error {
117+
// nil response from JSON.(M)GET (cmd.baseCmd.err will be "redis: nil")
118+
if cmd.baseCmd.Err() == Nil {
119+
cmd.val = ""
120+
return Nil
121+
}
117122

123+
// Handle other base command errors
118124
if cmd.baseCmd.Err() != nil {
119-
cmd.val = ""
120125
return cmd.baseCmd.Err()
121126
}
122127

@@ -128,7 +133,10 @@ func (cmd *JSONCmd) readReply(rd *proto.Reader) error {
128133
if err != nil {
129134
return err
130135
}
136+
137+
// Empty array could indicate no results found for JSON path
131138
if size == 0 {
139+
cmd.val = ""
132140
return Nil
133141
}
134142

json_test.go

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,6 @@ var _ = Describe("JSON Commands", Label("json"), func() {
263263
Expect(err).NotTo(HaveOccurred())
264264
Expect(res).To(Equal("OK"))
265265

266-
_, err = client.JSONGet(ctx, "this-key-does-not-exist", "$").Result()
267-
Expect(err).To(HaveOccurred())
268-
Expect(err).To(BeIdenticalTo(redis.Nil))
269-
270266
resArr, err := client.JSONArrIndex(ctx, "doc1", "$.store.book[?(@.price<10)].size", 20).Result()
271267
Expect(err).NotTo(HaveOccurred())
272268
Expect(resArr).To(Equal([]int64{1, 2}))
@@ -681,6 +677,54 @@ var _ = Describe("JSON Commands", Label("json"), func() {
681677
Expect(cmd2.Val()[0]).To(Or(Equal([]interface{}{"boolean"}), Equal("boolean")))
682678
})
683679
})
680+
681+
Describe("JSON Nil Handling", func() {
682+
It("should return redis.Nil for non-existent key", func() {
683+
_, err := client.JSONGet(ctx, "non-existent-key", "$").Result()
684+
Expect(err).To(Equal(redis.Nil))
685+
})
686+
687+
It("should return redis.Nil for non-existent path in existing key", func() {
688+
err := client.JSONSet(ctx, "test-key", "$", `{"a": 1, "b": "hello"}`).Err()
689+
Expect(err).NotTo(HaveOccurred())
690+
691+
_, err = client.JSONGet(ctx, "test-key", "$.nonexistent").Result()
692+
Expect(err).To(Equal(redis.Nil))
693+
})
694+
695+
It("should distinguish empty array from nil", func() {
696+
err := client.JSONSet(ctx, "test-key", "$", `{"arr": [], "obj": {}}`).Err()
697+
Expect(err).NotTo(HaveOccurred())
698+
699+
// Empty array should return the array, not nil
700+
val, err := client.JSONGet(ctx, "test-key", "$.arr").Result()
701+
Expect(err).NotTo(HaveOccurred())
702+
Expect(val).To(Equal("[[]]"))
703+
704+
// Non-existent field should return nil
705+
_, err = client.JSONGet(ctx, "test-key", "$.missing").Result()
706+
Expect(err).To(Equal(redis.Nil))
707+
})
708+
709+
It("should handle multiple paths with mixed results", func() {
710+
err := client.JSONSet(ctx, "test-key", "$", `{"a": 1, "b": 2}`).Err()
711+
Expect(err).NotTo(HaveOccurred())
712+
713+
// Path that exists
714+
val, err := client.JSONGet(ctx, "test-key", "$.a").Result()
715+
Expect(err).NotTo(HaveOccurred())
716+
Expect(val).To(Equal("[1]"))
717+
718+
// Path that doesn't exist
719+
_, err = client.JSONGet(ctx, "test-key", "$.c").Result()
720+
Expect(err).To(Equal(redis.Nil))
721+
})
722+
723+
AfterEach(func() {
724+
// Clean up test keys
725+
client.Del(ctx, "test-key", "non-existent-key")
726+
})
727+
})
684728
}
685729
})
686730

0 commit comments

Comments
 (0)