如何在Python中替换JSON格式字符串中的变量?
问题:动态生成带变量时间的Elasticsearch查询JSON字符串
我有一个固定格式的Elasticsearch查询JSON字符串:
json_data_string = "{\"size\":0,\"query\":{\"bool\":{\"must\":[{\"range\":{\"@timestamp\":{\"time_zone\":\"+09:00\",\"gte\":\"2023-01-24T00:00:00.000Z\",\"lt\":\"2023-01-25T00:00:00.000Z\"}}},{\"term\":{\"serviceid.keyword\":{\"value\":\"430011397\"}}}]}},\"aggs\":{\"by_day\":{\"auto_date_histogram\":{\"field\":\"@timestamp\",\"minimum_interval\":\"minute\"},\"aggs\":{\"agg-type\":{\"terms\":{\"field\":\"nxlogtype.keyword\",\"size\":1000},\"aggs\":{\"my-sub-agg-name\":{\"avg\":{\"field\":\"size\"}}}}}}}}"
现在想把其中的gte字段值换成循环生成的时间变量,比如通过以下循环迭代生成多个不同时间的查询JSON:
from datetime import datetime, timedelta fmt = '%Y-%m-%d %H:%M:%S' d1 = datetime.strptime('2010-01-01 00:00:00', fmt) d2 = datetime.strptime('2010-01-02 00:00:00', fmt) minutesDiff = (d2 - d1).days * 24 * 60 for n in range(minutesDiff): current_time = d1 + timedelta(minutes=n) # 这里需要生成替换gte后的JSON字符串
尝试直接用字符串的format()方法,但因为JSON本身包含大量{},导致语法冲突,无法正常替换,请问该怎么实现?
方法1:用Python字典构建查询(推荐)
直接把查询结构定义为Python字典,修改特定字段更直观,最后转成JSON字符串,完全避免字符串格式化的冲突问题:
import json from datetime import datetime, timedelta # 定义查询的字典结构 query_template = { "size": 0, "query": { "bool": { "must": [ { "range": { "@timestamp": { "time_zone": "+09:00", "gte": "", # 留空后续赋值 "lt": "2023-01-25T00:00:00.000Z" } } }, { "term": { "serviceid.keyword": { "value": "430011397" } } } ] } }, "aggs": { "by_day": { "auto_date_histogram": { "field": "@timestamp", "minimum_interval": "minute" }, "aggs": { "agg-type": { "terms": { "field": "nxlogtype.keyword", "size": 1000 }, "aggs": { "my-sub-agg-name": { "avg": { "field": "size" } } } } } } } } fmt = '%Y-%m-%d %H:%M:%S' d1 = datetime.strptime('2010-01-01 00:00:00', fmt) d2 = datetime.strptime('2010-01-02 00:00:00', fmt) minutesDiff = (d2 - d1).days * 24 * 60 for n in range(minutesDiff): current_time = d1 + timedelta(minutes=n) # 转换为ES需要的时间格式(带Z的UTC格式) gte_time = current_time.strftime('%Y-%m-%dT%H:%M:%S.000Z') # 修改字典中的gte字段 query_template["query"]["bool"]["must"][0]["range"]["@timestamp"]["gte"] = gte_time # 转成JSON字符串 json_str = json.dumps(query_template) print(json_str)
方法2:使用字符串格式化(需转义原有大括号)
如果一定要基于原始字符串修改,需要把JSON中所有原本的{}替换为{{}},然后把要替换的gte值位置用{gte_time}作为占位符,避免format()方法混淆:
from datetime import datetime, timedelta # 转义原始JSON中的所有{}为{{}},并把gte的值替换为占位符{gte_time} json_template = """{{"size":0,"query":{{"bool":{{"must":[{{"range":{{"@timestamp":{{"time_zone":"+09:00","gte":"{gte_time}","lt":"2023-01-25T00:00:00.000Z"}}}}}},{{"term":{{"serviceid.keyword":{{"value":"430011397"}}}}}}]}}}},"aggs":{{"by_day":{{"auto_date_histogram":{{"field":"@timestamp","minimum_interval":"minute"}},"aggs":{{"agg-type":{{"terms":{{"field":"nxlogtype.keyword","size":1000}},"aggs":{{"my-sub-agg-name":{{"avg":{{"field":"size"}}}}}}}}}}}}""" fmt = '%Y-%m-%d %H:%M:%S' d1 = datetime.strptime('2010-01-01 00:00:00', fmt) d2 = datetime.strptime('2010-01-02 00:00:00', fmt) minutesDiff = (d2 - d1).days * 24 * 60 for n in range(minutesDiff): current_time = d1 + timedelta(minutes=n) gte_time = current_time.strftime('%Y-%m-%dT%H:%M:%S.000Z') # 替换占位符生成JSON字符串 json_str = json_template.format(gte_time=gte_time) print(json_str)
注意点
- 方法1更易于维护,后续修改其他字段(比如
lt、serviceid)也更方便,不容易出错; - 方法2适合快速修改短字符串,但如果JSON结构复杂,转义大括号容易遗漏,不推荐。
内容的提问来源于stack exchange,提问作者sclee1
相关产品推荐
相关产品推荐

