How to specify the level of json.loads()?
<p>I have a JSON string to be loaded:</p>

<pre><code>{"a": 1, "b": {"c": 123} }
</code></pre>

<p>If I use <code>json.loads</code>, it will load <code>{"c": 123}</code> as a <code>dict</code>. However, I don't want that to happen.</p>

<p>I want to be able to access the string directly, without interpreting the internal object in to a dict, like so:</p>

<p><code>json_dict['b'] == '{"c": 123}'</code></p>

<p>rather than,</p>

<p><code>json_dict['b'] == {"c": 123}</code></p>

<p>since the format (like spaces) and order (which will be random in a <code>dict</code>) may change and the exact string is needed to do an RSA verification.</p>

<p>The actual code follows:</p>

<pre><code>r = requests.get('https://openapi.alipaydev.com/gateway.do', params)
print(r.text) 
response = json.loads(r.text)
print(response)
alipay_response = response['alipay_trade_precreate_response']
print(alipay_response['code'])
</code></pre>

<p>The output is:</p>

<pre><code>{"alipay_trade_precreate_response":{"code":"10000","msg":"Success","out_trade_no":"123","qr_code":"https:\/\/qr.alipay.com\/bax08377e7kxveupoqnt001c"},"sign":"EqocoROqXbpkGdkFZakEkoOymGS7+UcvNi1YmcQffF4wtyQcj/RTO1sLHY8tWZFx0rxQAPjkX+7Hrszn4pNWkuBbM/c88oEbxYc+pCvnF49SHZmfkBqY6eJlLIHgPHXus5KFtvlMmkzANNHmD7c72FLDAbvMHKVyEcRPkU9ANIk="}
{'sign': 'EqocoROqXbpkGdkFZakEkoOymGS7+UcvNi1YmcQffF4wtyQcj/RTO1sLHY8tWZFx0rxQAPjkX+7Hrszn4pNWkuBbM/c88oEbxYc+pCvnF49SHZmfkBqY6eJlLIHgPHXus5KFtvlMmkzANNHmD7c72FLDAbvMHKVyEcRPkU9ANIk=', 'alipay_trade_precreate_response': {'out_trade_no': '123', 'qr_code': 'https://qr.alipay.com/bax08377e7kxveupoqnt001c', 'msg': 'Success', 'code': '10000'}}
10000
</code></pre>

<p>We can see that <code>response['alipay_trade_precreate_response']</code> is a <code>dict</code>, and the order is different from the string. I need the string so I can verify the RSA signature.</p>

<p>To directly answer your question: no, <code>json.loads</code> doesn't support this.</p>

<p>I've included two ways to accomplish your goal below. The first is very robust and relies on the lexer from <a href="https://pypi.python.org/pypi/ijson/" rel="nofollow"><code>ijson</code></a>. The second method is much less robust and relies on a regular expression.</p>

<pre><code>json_string = '{"alipay_trade_precreate_response":{"code":"10000","msg":"Success","out_trade_no":"123","qr_code":"https:\/\/qr.alipay.com\/bax08377e7kxveupoqnt001c"},"sign":"EqocoROqXbpkGdkFZakEkoOymGS7+UcvNi1YmcQffF4wtyQcj/RTO1sLHY8tWZFx0rxQAPjkX+7Hrszn4pNWkuBbM/c88oEbxYc+pCvnF49SHZmfkBqY6eJlLIHgPHXus5KFtvlMmkzANNHmD7c72FLDAbvMHKVyEcRPkU9ANIk="}'

# METHOD 1:
# ---------
import ijson
import io

def get_raw_dict_string(json_string, key='alipay_trade_precreate_response'):
    tokens = [[pos, symbol] for pos, symbol in ijson.backends.python.Lexer(io.StringIO(json_string))]
    if tokens[0][1] != '{':
        raise Exception("not a dictionary")

    start = None
    end = None
    i = 0
    level = 0
    while i &lt; len(tokens):
        pos, symbol = tokens[i]
        if symbol == '{':
            level += 1
        elif symbol == '}':
            level -= 1
            if level == 1:
                end = pos
                break
        elif level == 1 and symbol[0] == '"':
            if ijson.backends.python.unescape(symbol[1:-1]) == key:
                if tokens[i+1][1] == ':' and tokens[i+2][1] == '{':
                    start = tokens[i+2][0]
                    i += 2
                    level += 1
        i += 1

    return json_string[start:end+1]

print(get_raw_dict_string(json_string))
# Output:
# {"code":"10000","msg":"Success","out_trade_no":"123","qr_code":"https:\/\/qr.alipay.com\/bax08377e7kxveupoqnt001c"}



# METHOD 2:
# ---------

import re
print(re.search(r'"alipay_trade_precreate_response"\s*:\s*({[^}]*})', json_string).group(1))
# Output:
# {"code":"10000","msg":"Success","out_trade_no":"123","qr_code":"https:\/\/qr.alipay.com\/bax08377e7kxveupoqnt001c"}
</code></pre>

python json