使用.format为JSON查询传动态值触发KeyError的解决咨询
解决方法
你的问题出在GraphQL查询字符串里的{}会被Python的str.format()误识别为占位符,导致KeyError。以下是三种可行的解决方式:
方式一:转义不需要替换的大括号
把查询中所有不需要动态替换的{}改成{{}}(双大括号在str.format()中会被解析为单个大括号),只保留startpmtexctndt和endpmtexctndt对应的{}作为占位符:
start_date = os.environ.get('5678') end_date = os.environ.get('1234') query = json.dumps({ "query": "query{{\r\n PmtInfoByFileid(pmttypcde:\"A2A*\",pmtstatuscde:\"SCHEDULED\", txnstatusctgrytxt:\"DIY_ACTIVE_TRANSACTIONS\",\r\n startpmtexctndt:\"{}\",endpmtexctndt:\"{}\",pagesize:10){{\r\n list{{custlpid \r\n pmttypcde\r\n txntypcde\r\n pmtcrtndt\r\n pmtexctndt\r\n debtorinfotxt\r\n pmtstatuscde\r\n debtoraccntnbr\r\n btchcntrlsumval\r\n MnyMvmntCrdtTrnsfrTxnByPmtinfoid{{\r\n pmtinstrctnid\r\n creditoraccntnbr\r\n creditortxt\r\n }}\r\n }}\r\n metadata{{\r\n pageNumber\r\n limit\r\n totalPages\r\n totalRecords\r\n }}\r\n }}\r\n".format(start_date, end_date), "variables": {} })
方式二:使用f-string转义
和方式一逻辑一致,只是改用f-string实现动态参数传递,同样需要把非占位符的{}转义为{{}}:
start_date = os.environ.get('5678') end_date = os.environ.get('1234') query = json.dumps({ "query": f"query{{\r\n PmtInfoByFileid(pmttypcde:\"A2A*\",pmtstatuscde:\"SCHEDULED\", txnstatusctgrytxt:\"DIY_ACTIVE_TRANSACTIONS\",\r\n startpmtexctndt:\"{start_date}\",endpmtexctndt:\"{end_date}\",pagesize:10){{\r\n list{{custlpid \r\n pmttypcde\r\n txntypcde\r\n pmtcrtndt\r\n pmtexctndt\r\n debtorinfotxt\r\n pmtstatuscde\r\n debtoraccntnbr\r\n btchcntrlsumval\r\n MnyMvmntCrdtTrnsfrTxnByPmtinfoid{{\r\n pmtinstrctnid\r\n creditoraccntnbr\r\n creditortxt\r\n }}\r\n }}\r\n metadata{{\r\n pageNumber\r\n limit\r\n totalPages\r\n totalRecords\r\n }}\r\n }}\r\n", "variables": {} })
方式三:使用GraphQL变量(推荐)
这是GraphQL的标准用法,完全避免字符串格式化的问题,同时更安全、可读性更高:
start_date = os.environ.get('5678') end_date = os.environ.get('1234') query = json.dumps({ "query": """ query($startDate: String!, $endDate: String!) { PmtInfoByFileid( pmttypcde:"A2A*", pmtstatuscde:"SCHEDULED", txnstatusctgrytxt:"DIY_ACTIVE_TRANSACTIONS", startpmtexctndt:$startDate, endpmtexctndt:$endDate, pagesize:10 ) { list { custlpid pmttypcde txntypcde pmtcrtndt pmtexctndt debtorinfotxt pmtstatuscde debtoraccntnbr btchcntrlsumval MnyMvmntCrdtTrnsfrTxnByPmtinfoid { pmtinstrctnid creditoraccntnbr creditortxt } } metadata { pageNumber limit totalPages totalRecords } } } """, "variables": { "startDate": start_date, "endDate": end_date } })
各方式对比
- 方式一、二适合快速修改现有代码,但查询复杂时转义操作容易出错;
- 方式三是GraphQL的最佳实践,能避免潜在的注入风险,代码结构更清晰,推荐长期使用。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

