Python构造Valhalla请求时双引号被替换为转义单引号导致报错
问题根因
出现转义单引号的核心原因是把Python原生字典/列表对象直接做了字符串插值:不管用f-string还是手动字符串拼接,只要把未序列化的Python列表、字典直接塞进字符串模板,Python会自动调用对象的__str__方法输出原生表示——也就是单引号包裹键名、嵌套结构带转义符的格式,不属于标准JSON。哪怕单独对某一段参数调用json.dumps,只要后续把序列化后的字符串和其他Python原生对象混着插值,还是会出现格式错乱。
正确实现方案
全程不要手动拼接JSON字符串,统一用Python标准库json做全量序列化,从根源避免格式错误:
- 第一步:先在Python中构造完整的请求参数字典,不要拆分字符串逐段拼接
- 写入提前准备好的
sources字段内容 - 把从Pandas Series提取的坐标转成字典列表,赋值给
targets字段 - 补全Valhalla矩阵API要求的其他必填参数(比如costing通行模式、返回字段配置等)
- 写入提前准备好的
- 第二步:对整个完整的参数字典调用一次
json.dumps(),直接生成符合规范的JSON请求体,生成后不要做任何额外的字符串拼接、插值操作 - 第三步:发请求时把序列化后的标准JSON字符串作为请求体传入,不要把Python原生对象直接传给请求接口
错误写法复现(会生成带转义单引号的非法请求)
import requests import pandas as pd # 示例坐标数据 coord_series = pd.Series([{"lat": 39.9042, "lon": 116.4074}, {"lat": 31.2304, "lon": 121.4737}]) sources = [{"lat": 30.5728, "lon": 104.0668}] targets = coord_series.to_list() # 错误操作:直接把Python列表/字典对象插值到字符串模板里 query = f'{{"sources": {sources}, "targets": {targets}, "costing": "auto"}}' # 此时打印query就能看到单引号、转义反斜杠,完全不符合JSON格式要求 resp = requests.post("http://你的本地Valhalla服务地址/matrix", data=query)
可直接运行的正确写法
import requests import json import pandas as pd coord_series = pd.Series([{"lat": 39.9042, "lon": 116.4074}, {"lat": 31.2304, "lon": 121.4737}]) # 1. 先组装完整的参数字典结构 payload = { "sources": [{"lat": 30.5728, "lon": 104.0668}], "targets": coord_series.to_list(), "costing": "auto", # 按接口文档补全其余必填参数即可 } # 2. 一次性序列化整个字典,输出标准双引号格式的合法JSON valid_json_query = json.dumps(payload) # 3. 传请求时指定Content-Type,传入序列化后的合法JSON resp = requests.post( "http://你的本地Valhalla服务地址/matrix", data=valid_json_query, headers={"Content-Type": "application/json"} ) # 更简便的写法:不需要手动调用json.dumps,直接把payload传给requests的json参数,请求库会自动完成标准序列化,自动补全请求头 # resp = requests.post("http://你的本地Valhalla服务地址/matrix", json=payload)
排查提示:如果按上述写法还是出现序列化异常,先检查从Pandas Series提取的坐标值是否为numpy原生数据类型(比如numpy.float64),
json.dumps默认不支持numpy类型,会抛出序列化错误或输出异常格式,遇到这类情况先把坐标值转成Python原生的int、float类型再组装参数即可。
内容的提问来源于stack exchange,提问作者Alberto Mario Castillo
相关产品推荐
相关产品推荐

