diff --git a/docs/source/format.rst b/docs/source/format.rst
index c12d3b2..de15bbb 100644
--- a/docs/source/format.rst
+++ b/docs/source/format.rst
@@ -274,7 +274,8 @@ All of these variables may be used in all of the following fields:
 * ``data``
 * ``request_headers``
 * ``response_strings``
-* ``response_json_paths`` (on the value side of the key value pair)
+* ``response_json_paths`` (in both the key and value, see
+  :ref:`json path substitution <json-subs>` for more info)
 * ``response_headers`` (on the value side of the key value pair)
 * ``response_forbidden_headers``
 * ``count`` and ``delay`` fields of ``poll``
diff --git a/docs/source/jsonpath.rst b/docs/source/jsonpath.rst
index f65db38..317603b 100644
--- a/docs/source/jsonpath.rst
+++ b/docs/source/jsonpath.rst
@@ -81,6 +81,31 @@ Examples like this can be found in one of gabbi's `own tests`_.
 There are more JSONPath examples in :doc:`example` and in the
 `jsonpath_rw`_ and `jsonpath_rw_ext`_ documentation.
 
+.. _json-subs:
+
+Substitution
+------------
+
+:ref:`Substitutions <state-substitution>` can be made in both the
+left (query) and right (expected) hand sides of the json path
+expression. When subtitutions are used in the query, care must be
+taken to ensure proper quoting of the resulting value. For example
+if there is a uuid (with hyphens) at ``$RESPONSE['$.id']`` then this
+expression may fail::
+
+    $.nested.structure.$RESPONSE['$.id'].name: foobar
+
+as it will evaluate to something like::
+
+   $.nested.structure.ADC8AAFC-D564-40D1-9724-7680D3C010C2.name: foobar
+
+which may be treated as an arithemtic expression by the json path
+parser. The test author should write::
+
+    $.nested.structure["$RESPONSE['$.id']"].name: foobar
+
+to quote the result of the substitution.
+
 .. _jsonpath_rw: http://jsonpath-rw.readthedocs.io/en/latest/
 .. _jsonpath_rw_ext: https://python-jsonpath-rw-ext.readthedocs.io/en/latest/
 .. _own tests: https://github.com/cdent/gabbi/blob/master/gabbi/tests/gabbits_intercept/data.yaml
diff --git a/gabbi/handlers/jsonhandler.py b/gabbi/handlers/jsonhandler.py
index da20af0..2f85360 100644
--- a/gabbi/handlers/jsonhandler.py
+++ b/gabbi/handlers/jsonhandler.py
@@ -75,11 +75,8 @@ class JSONHandler(base.ContentHandler):
 
     def action(self, test, path, value=None):
         """Test json_paths against json data."""
-        # NOTE: This process has some advantages over other process that
-        # might come along because the JSON data has already been
-        # processed (to provided for the magic template replacing).
-        # Other handlers that want access to data structures will need
-        # to do their own processing.
+        # Do template expansion in the left hand side.
+        path = test.replace_template(path)
         try:
             match = self.extract_json_path_value(
                 test.response_data, path)
diff --git a/gabbi/tests/gabbits_intercept/json-left-side.yaml b/gabbi/tests/gabbits_intercept/json-left-side.yaml
new file mode 100644
index 0000000..6ce342c
--- /dev/null
+++ b/gabbi/tests/gabbits_intercept/json-left-side.yaml
@@ -0,0 +1,37 @@
+defaults:
+  request_headers:
+      content-type: application/json
+  verbose: True
+
+tests:
+- name: left side json one
+  desc: for reuse on the next test
+  POST: /
+  data:
+      alpha: alpha1
+      beta: beta1
+
+- name: expand left side
+  POST: /
+  data:
+      alpha1: alpha
+      beta1: beta
+  response_json_paths:
+      $["$RESPONSE['$.alpha']"]: alpha
+
+- name: expand environ left side
+  POST: /
+  data:
+      alpha1: alpha
+      beta1: beta
+      1: cow
+  response_json_paths:
+      $.['$ENVIRON['ONE']']: cow
+
+- name: set key and value
+  GET: /jsonator?key=$ENVIRON['ONE']&value=10
+
+- name: check key and value
+  GET: /jsonator?key=$ENVIRON['ONE']&value=10
+  response_json_paths:
+      $.["$ENVIRON['ONE']"]: $RESPONSE['$['1']']
diff --git a/gabbi/tests/simple_wsgi.py b/gabbi/tests/simple_wsgi.py
index fabb7e3..b7528ff 100644
--- a/gabbi/tests/simple_wsgi.py
+++ b/gabbi/tests/simple_wsgi.py
@@ -107,6 +107,11 @@ class SimpleWsgi(object):
             # fall through if we've ended the loop
         elif path_info == '/cookie':
             headers.append(('Set-Cookie', 'session=1234; domain=.example.com'))
+        elif path_info == '/jsonator':
+            json_data = json.dumps({query_data['key'][0]:
+                                    query_data['value'][0]})
+            start_response('200 OK', [('Content-Type', 'application/json')])
+            return [json_data.encode('utf-8')]
 
         start_response('200 OK', headers)