简体   繁体   中英

How to return this valid json data in Python?

I tested using Python to translate a curl to get some data.

import requests
import json

username="abc"
password="123"
headers = {
    'Content-Type': 'application/json',
}
params = (
    ('version', '2017-05-01'),
)

data = '{"text":["This is message one."], "id":"en-es"}'
response = requests.post('https://somegateway.service/api/abc', headers=headers, params=params, data=data, auth=(username, password))
print(response.text)

The above works fine. It returns json data. It seems ["This is message one."] is a list. I want to use a variable that loads a file to replace this list. I tried:

with open(f,"r",encoding='utf-8') as fp:
    file_in_list=fp.read().splitlines()
    toStr=str(file_in_list)
    data = '{"text":'+toStr+', "id":"en-es"}'
    response = requests.post('https://somegateway.service/api/abc', headers=headers, params=params, data=data, auth=(username, password))
    print(response.text)

But it returned error below.

{
  "code" : 400,
  "error" : "Mapping error, invalid JSON"
}

Can you help? How can I have valid response.text?

Thanks.

update:

The content of f contains only five lines below:

This is message one.
this is 2.
this is three.
this is four.
this is five.

The reason your existing code fails is that str applied to a list of strings will only rarely give you valid JSON. They're not intended to do the same thing. JSON only allows double-quoted strings; Python allows both single- and double-quoted strings. And, unless your strings all happen to include ' characters, Python will render them with single quotes:

>>> print(["abc'def"]) # gives you valid JSON, but only by accident
["abc'def"]
>>> print(["abc"]) # does not give you valid JSON
['abc']

If you want to get the valid JSON encoding of a list of strings, don't try to trick str into giving you valid JSON by accident, just use the json module:

toStr = json.dumps(file_in_list)

But, even more simply, you shouldn't be trying to figure out how to construct JSON strings in the first place. Just create a dict and json.dumps the whole thing:

data = {"text": file_in_list, "id": "en-es"}
data_str = json.dumps(data)

Being able to do this is pretty much the whole point of JSON: it's a simple way to automatically serialize all of the types that are common to all the major scripting languages.


Or, even better, let requests do it for you by passing a json argument instead of a data argument:

data = {"text": file_in_list, "id": "en-es"}
response = requests.post('https://somegateway.service/api/abc', headers=headers, params=params, json=data, auth=(username, password))

This also automatically takes care of setting the Content-Type header to application/json for you. You weren't doing that—and, while many servers will accept your input without it, it's illegal, and some servers will not allow it.


For more details, see the section More complicated POST requests in the requests docs. But there really aren't many more details.

tldr;

toStr = json.dumps(file_in_list)

Explanation

Assuming your file contains something like String_A String_B

You need to ensure that toStr is:

  1. Enclosed by [ and ]
  2. Every String in the list is enclosed by quotation marks.

So your raw json (as a String) is equal to '{"text":["String_A", "String_B"], "id":"en-es"}'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM