首页 > 解决方案 > 如何将此 URL 参数字典编码为有效字符串?

问题描述

我有一个params看起来像这样的 Python 字典:

{
    "request": {
        "metadataOnly":False,
        "latitude": 80.12345,
        "treatmentFlags":[
            "simple_search_1_1",
            "simple_search_desktop_v3_full_bleed",
            "flexible_dates_options_extend_one_three_seven_days"
        ]
    }
}

我想params转换成这个字符串:

%7B%22request%22%3A%7B%22metadataOnly%22%3A%22false%22%2C%22latitude%22%3A%2280.12345%22%2C%22treatmentFlags%22%3A%5B%22simple_search_1_1%22%2C%22simple_search_desktop_v3_full_bleed%22%2C%22flexible_dates_options_extend_one_three_seven_days%22%5D%7D%7D

因为该字符串在我正在查询的 URL 中有效。该字符串在使用Advanced REST Client解码时如下所示:

{"request":{"metadataOnly":"false","latitude":"80.12345","treatmentFlags":["simple_search_1_1","simple_search_desktop_v3_full_bleed","flexible_dates_options_extend_one_three_seven_days"]}}

如何将params或任何此类 Python 字典转换为我描述的有效字符串?

标签: pythonpython-3.xresturlget

解决方案


您要实现的是两种编码技术的组合:

  • JSON 编码(将字典转换为字符串)
  • URL 编码(对字符串进行编码以使其在 URL 查询字符串中使用安全)

在这个答案中,我包含了两个 Python 示例,逐步分解,以及一个Tl;Dr最小编码 + 解码示例,供那些不需要/想要完整解释其工作原理的人使用。

第一个显示如何根据问题中所需的最终结果字符串将 dict/list 转换为 URL 编码的 JSON 字符串,第二个示例显示如何反转该过程- 将 URL 编码的 JSON 字符串转换回原始 JSON 字符串,然后将其转换回它的原始dict对象。

TL;博士; 完整的代码,最少的解释

向下滚动以查看详细的分步说明。此代码块是 TL;DR; 示例 - 将编码覆盖到 URL 字符串中,然后返回到 dict,使用最少的注释和节省空间的格式。

import urllib.parse
import json

data = {
    "request": { "metadataOnly":False, "latitude": 80.12345,
        "treatmentFlags":["simple_search_1_1", "simple_search_desktop_v3_full_bleed", "flexible_dates_options_extend_one_three_seven_days"]}
}

j = json.dumps(data)             # Convert 'data' into a JSON string

u = urllib.parse.quote_plus(j)   # URL encode the JSON string
# 'u' now contains the desired result, starting with '%7B%22request%22%3A%7B%22metadataOnly%22%3A%22f' ...

# Reversing the process (url string back to dict)

# Decode the URL encoded string 'u' back into a normal JSON string
dec = urllib.parse.unquote_plus(u)
# Import the JSON string back into a Python dict (jd is effectively the same as 'data')
jd = json.loads(dec)
print(jd['request']['treatmentFlags'])
# Output: ['simple_search_1_1', 'simple_search_desktop_v3_full_bleed', 'flexible_dates_options_extend_one_three_seven_days']

Python 示例(将 dict / 列表编码为 URL 编码的 JSON)

导入urllib.parsejson模块 + 创建数据对象

首先我们需要导入两个模块:urllib.parsejson. dict然后将需要编码的原始声明为变量data

import urllib.parse
import json

data = {
    "request": {
        "metadataOnly":False,
        "latitude": 80.12345,
        "treatmentFlags":[
            "simple_search_1_1",
            "simple_search_desktop_v3_full_bleed",
            "flexible_dates_options_extend_one_three_seven_days"
        ]
    }
}

使用 JSON 将变量“数据”编码到变量“j”中

dumps从模块中使用,您可以json将 Python转换为 JSON 编码字符串dictlist

j = json.dumps(data)

# You can see that 'j' is now a string
print(type(j))
# Output:
#  <class 'str'>

# If we print 'j', you can see the contents have been encoded as JSON
print(j)
# Output:
#
#   {"request": {"metadataOnly": false, "latitude": 80.12345, 
#   "treatmentFlags": ["simple_search_1_1", 
#   "simple_search_desktop_v3_full_bleed", 
#   "flexible_dates_options_extend_one_three_seven_days"]}}

将“j”编码为 URL 编码变量“u”

现在我们将 JSON 字符串转换为变量 'u' 中的编码 URL 字符,以便在 URL 查询字符串中使用它是安全的

####
# Now we convert the JSON string into encoded URL characters in variable 'u'
# so that it's safe for use in a URL query string
####
u = urllib.parse.quote_plus(j)

# If we print the variable 'u', you can see it's now encoded in URL safe format
print(u)
# Output:
#
#   %7B%22request%22%3A+%7B%22metadataOnly%22%3A+false%2C+%22latitude
#   %22%3A+80.12345%2C+%22treatmentFlags%22%3A+%5B%22simple_search_1_1
#   %22%2C+%22simple_search_desktop_v3_full_bleed
#   %22%2C+%22flexible_dates_options_extend_one_three_seven_days%22%5D%7D%7D

反转过程(将 URL 编码的 JSON 解码回字典 / 列表)

如果您稍后需要将 URL 编码的字符串解码回 JSON 和/或字典,我们可以像这样反转该过程:

再次导入模块 + 声明 URL 编码字符串 'u'

首先我们导入urllib.parseand json,就像之前一样,并将 URL 编码的字符串声明为u

import urllib.parse
import json

u = "%7B%22request%22%3A+%7B%22metadataOnly%22%3A+false%2C+%22latitude" + \
    "%22%3A+80.12345%2C+%22treatmentFlags%22%3A+%5B%22simple_search_1_1" + \
    "%22%2C+%22simple_search_desktop_v3_full_bleed" + \
    "%22%2C+%22flexible_dates_options_extend_one_three_seven_days%22%5D%7D%7D"

将 URL 编码字符串解码回原始 JSON 字符串

unquote_plus从模块中使用urllib.parse,您可以解码已被 URL 编码的字符串(即%22hello%20world%22

dec = urllib.parse.unquote_plus(u)

print(dec)
# Output:
#
# {"request": {"metadataOnly": false, "latitude": 80.12345, "treatmentFlags": ["simple_search_1_1", "simple_search_desktop_v3_full_bleed", "flexible_dates_options_extend_one_three_seven_days"]}}

将 JSON 字符串加载到标准 Python 字典/列表中

使用loadsfromjson模块,您可以将 JSON 字符串 ( str) 或bytes对象导入标准 Pythondictlist(取决于您是在解码 JSON 列表还是字典)

jd = json.loads(dec)

print(jd['request']['metadataOnly'])
# Output: False

print(jd['request']['treatmentFlags'])
# Output: 
#
#   ['simple_search_1_1', 'simple_search_desktop_v3_full_bleed', 'flexible_dates_options_extend_one_three_seven_days']

推荐阅读