@@ -3142,11 +3142,14 @@ def _contains_value(self, field, value):
31423142 return Value (field ._dumps (value ), converter = False )
31433143
31443144 @staticmethod
3145- def _path (keys , suffix = '' ):
3145+ def _path_index (idx ):
3146+ return '[#%d]' % idx if idx < 0 else '[%d]' % idx
3147+
3148+ def _path (self , keys , suffix = '' ):
31463149 parts = ['$' ]
31473150 for k in keys :
31483151 if isinstance (k , int ):
3149- parts .append ('[#%d]' % k if k < 0 else '[%d]' % k )
3152+ parts .append (self . _path_index ( k ) )
31503153 else :
31513154 k = str (k ).replace ('\\ ' , '\\ \\ ' ).replace ('"' , '\\ "' )
31523155 parts .append ('."%s"' % k )
@@ -3415,6 +3418,12 @@ def wrapper(value):
34153418 compact = False )
34163419 return wrapper
34173420
3421+ @staticmethod
3422+ def _path_index (idx ):
3423+ if idx < 0 :
3424+ return '[last]' if idx == - 1 else '[last%d]' % (idx + 1 )
3425+ return '[%d]' % idx
3426+
34183427 def extract (self , field , keys ):
34193428 if not keys :
34203429 return field
@@ -3476,7 +3485,7 @@ def update(self, field, value):
34763485 return fn .JSON_MERGE_PATCH (field , self ._json_value (field , value ))
34773486
34783487 def contains (self , field , keys , value ):
3479- # JSON_CONTAINS returns 0/1; wrap in `= 1` so it composes cleanly in
3488+ # JSON_CONTAINS returns 0/1, wrap in `= 1` so it composes cleanly in
34803489 # boolean contexts (NOT, AND, etc.).
34813490 path_args = (self ._path (keys ),) if keys else ()
34823491 call = fn .JSON_CONTAINS (field , self ._contains_value (field , value ),
0 commit comments