如何指定级别json.loads()?

2024-06-16 14:24:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个JSON字符串要加载:

{"a": 1, "b": {"c": 123} }

如果我使用json.loads,它将把{"c": 123}作为dict加载。但是,我不想发生这种事。在

我希望能够直接访问字符串,而无需将内部对象解释为dict,如下所示:

json_dict['b'] == '{"c": 123}'

而不是

json_dict['b'] == {"c": 123}

因为格式(如空格)和顺序(在dict中是随机的)可能会改变,并且需要精确的字符串来进行RSA验证。在

实际代码如下:

^{pr2}$

输出为:

{"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

我们可以看到response['alipay_trade_precreate_response']是一个dict,其顺序与字符串不同。我需要这个字符串以便我可以验证RSA签名。在


Tags: no字符串json顺序responsecodemsgout
1条回答
网友
1楼 · 发布于 2024-06-16 14:24:04

要直接回答您的问题:不,json.loads不支持此功能。在

下面我介绍了两种实现目标的方法。第一个非常健壮,依赖于^{}中的lexer。第二种方法的健壮性要差得多,并且依赖于正则表达式。在

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 < 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"}

相关问题 更多 >