Python请求:多部分,一部分作为json

时间:2019-05-22 02:31:25

标签: python json python-requests multipartform-data

Netflix的Genie API使用JSONmultipart,其中request中包含application/json的一部分,而attachment中包含任意数量的application/octet-stream

请求使普通的JSON POST非常简单:

requests.post(
  url=self.host + self.endpoint,
  json={
    "version" : "1.0",
    "user" : "genie",
    "name" : "List * ... Directories bash job",
    "description" : "Genie 3 Test Job",
    "configs" : [ "/home/travis/build/Netflix/genie/genie-web/build/resources/test/com/netflix/genie/web/controllers/JobRestControllerIntegrationTests/job/config1" ],
    "dependencies" : [ "/home/travis/build/Netflix/genie/genie-web/build/resources/test/com/netflix/genie/web/controllers/JobRestControllerIntegrationTests/job/dep1" ],
    "setupFile" : "/home/travis/build/Netflix/genie/genie-web/build/resources/test/com/netflix/genie/web/controllers/JobRestControllerIntegrationTests/job/jobsetupfile",
    "commandArgs" : "-c 'echo hello world'",
    "clusterCriterias" : [ {
      "tags" : [ "localhost" ]
    } ],
    "commandCriteria" : [ "bash" ],
  },
)

该命令是受限制的,因此,如果要发送大命令(查询),则最好使用附件。

对于请求,请求多部分也不难:

requests.post(
  url=self.host + self.endpoint,
  json={
    "version" : "1.0",
    "user" : "genie",
    "name" : "List * ... Directories bash job",
    "description" : "Genie 3 Test Job",
    "configs" : [ "/home/travis/build/Netflix/genie/genie-web/build/resources/test/com/netflix/genie/web/controllers/JobRestControllerIntegrationTests/job/config1" ],
    "dependencies" : [ "/home/travis/build/Netflix/genie/genie-web/build/resources/test/com/netflix/genie/web/controllers/JobRestControllerIntegrationTests/job/dep1" ],
    "setupFile" : "/home/travis/build/Netflix/genie/genie-web/build/resources/test/com/netflix/genie/web/controllers/JobRestControllerIntegrationTests/job/jobsetupfile",
    "commandArgs" : "-c 'cat query.sql'",
    "clusterCriterias" : [ {
      "tags" : [ "localhost" ]
    } ],
    "commandCriteria" : [ "bash" ],
  },
  files={
    "attachment": (
      'query.sql',
      'select count(1) from small_table;',
      'application/octet-stream'
    ),
  },
)

除非files存在,否则它将忽略json,如果我将json更改为data,它将是一种形式。我可以将JSON字典移到files字典中,但是它似乎没有像JSON一样处理,现在我需要使用该包对其进行编码?

我问,因为使用requests处理参数和响应对象中的json时,我怀疑它也会以多部分形式在某处处理它,否则我只是将{{1}引入json }

另外:

  1. 似乎没有一种方法可以发送不止一个名为json.dumps(...)的部件,如果您需要多个附件,则api可以允许/期望该部件。 [正如我的评论,可以通过将attachment更改为列表名称与文件对的列表来完成。]
  2. 示例请求显示零件标题的名称未加引号,例如filesContent-Disposition: form-data; name=request,而请求包似乎生成了Content-Disposition: form-data; name=attachment

1 个答案:

答案 0 :(得分:1)

“我可以将JSON dict移到文件dict中,但似乎无法作为JSON处理”

  
      
  1. 您可以将字典转储到磁盘上的JSON文件中。
  2.   
     

tempfile.TemporaryFile可以使用。 转储,请求,清理并重复

“否则,我将仅为json.dumps(...)引入json”

  
      
  1. 如果您需要保留命令并在运行期间建立请求,则可以这样做(此用例忽略1)。但是,请记住将转储转换为io.BytesIO对象,以便请求可以计算内容长度标头。
  2.   
     

另外,请记住将文件的内容类型传递为“ application / octet-stream”而不是“ plain / text”

“示例请求显示零件标题的名称未加引号”

  

我认为这不重要。 RFC 2183记录了长度<78但包含tspecials should的参数值表示为带引号的字符串。

     

虽然name参数的值不包含tspecials,但这对于短值IMO的处理更为可靠。