@@ -69,19 +69,66 @@ func (ctx *jsonpathCtx) evalOperation(
6969 case jsonpath .OpCompEqual , jsonpath .OpCompNotEqual ,
7070 jsonpath .OpCompLess , jsonpath .OpCompLessEqual ,
7171 jsonpath .OpCompGreater , jsonpath .OpCompGreaterEqual :
72- res , err := ctx .evalComparison (op , jsonValue , true /* unwrapRight */ )
72+ res , err := ctx .evalComparison (op , jsonValue )
7373 if err != nil {
7474 return convertFromBool (jsonpathBoolUnknown ), err
7575 }
7676 return convertFromBool (res ), nil
7777 case jsonpath .OpAdd , jsonpath .OpSub , jsonpath .OpMult ,
7878 jsonpath .OpDiv , jsonpath .OpMod :
7979 return ctx .evalArithmetic (op , jsonValue )
80+ case jsonpath .OpLikeRegex :
81+ res , err := ctx .evalRegex (op , jsonValue )
82+ if err != nil {
83+ return convertFromBool (jsonpathBoolUnknown ), err
84+ }
85+ return convertFromBool (res ), nil
8086 default :
8187 panic (errors .AssertionFailedf ("unhandled operation type" ))
8288 }
8389}
8490
91+ func (ctx * jsonpathCtx ) evalRegex (
92+ op jsonpath.Operation , jsonValue json.JSON ,
93+ ) (jsonpathBool , error ) {
94+ l , err := ctx .evalAndUnwrapResult (op .Left , jsonValue , true /* unwrap */ )
95+ if err != nil {
96+ return jsonpathBoolUnknown , err
97+ }
98+ if len (l ) != 1 {
99+ return jsonpathBoolUnknown , errors .AssertionFailedf ("left is not a single string" )
100+ }
101+ if l [0 ].Type () != json .StringJSONType {
102+ return jsonpathBoolUnknown , nil
103+ }
104+ // AsText() provides the correct string representation for regex pattern
105+ // matching by returning raw characters instead of their escaped JSON string
106+ // representations.
107+ //
108+ // Examples:
109+ // - For a JSON string with a backslash ("\\"): AsText() returns two
110+ // backslashes ("\\"), while String() returns "\"\\\\\"" (two escaped
111+ // backslashes enclosed in quotes).
112+ // - For a JSON string with a newline ("\n"): AsText() returns an actual
113+ // newline character ("\n"), while String() returns "\"\\n\"" (an escaped
114+ // backslash and 'n' enclosed in quotes)
115+ text , err := l [0 ].AsText ()
116+ if err != nil {
117+ return jsonpathBoolUnknown , err
118+ }
119+
120+ regexOp := op .Right .(jsonpath.Regex )
121+ r , err := ctx .evalCtx .ReCache .GetRegexp (regexOp )
122+ if err != nil {
123+ return jsonpathBoolUnknown , err
124+ }
125+ res := r .MatchString (* text )
126+ if ! res {
127+ return jsonpathBoolFalse , nil
128+ }
129+ return jsonpathBoolTrue , nil
130+ }
131+
85132func (ctx * jsonpathCtx ) evalLogical (
86133 op jsonpath.Operation , current json.JSON ,
87134) (jsonpathBool , error ) {
@@ -143,17 +190,14 @@ func (ctx *jsonpathCtx) evalLogical(
143190// right paths satisfy the condition. In strict mode, even if a pair has been
144191// found, all pairs need to be checked for errors.
145192func (ctx * jsonpathCtx ) evalComparison (
146- op jsonpath.Operation , jsonValue json.JSON , unwrapRight bool ,
193+ op jsonpath.Operation , jsonValue json.JSON ,
147194) (jsonpathBool , error ) {
148- // The left argument results are always auto-unwrapped.
195+ // The left and right argument results are always auto-unwrapped.
149196 left , err := ctx .evalAndUnwrapResult (op .Left , jsonValue , true /* unwrap */ )
150197 if err != nil {
151198 return jsonpathBoolUnknown , err
152199 }
153- // The right argument results are conditionally unwrapped. Currently, it is
154- // always unwrapped, but in the future for operations like like_regex, we
155- // don't want to unwrap the right argument.
156- right , err := ctx .evalAndUnwrapResult (op .Right , jsonValue , unwrapRight )
200+ right , err := ctx .evalAndUnwrapResult (op .Right , jsonValue , true /* unwrap */ )
157201 if err != nil {
158202 return jsonpathBoolUnknown , err
159203 }
0 commit comments