Flask向外部URL提交JSON报错:JSONDecodeError及Not Acceptable求助
Hey there, let's tackle the two frustrating issues you're facing with your Flask app. I'll break down each problem, explain what's causing it, and show you step-by-step fixes—plus some extra tweaks to make your code more robust.
1. Fixing the "Not Acceptable" (406) Error When Sending JSON
The 406 error means the external server can't return a response that matches your request's expectations, or there's a misstep in how you're formatting your JSON payload. Here's how to fix it:
What's Going Wrong
In your code, you're manually serializing data with json.dumps(data) and setting the Content-Type header, but you're not telling the server you expect a JSON response in return. Also, using json.dumps() with the data parameter is redundant—Requests has a built-in way to handle JSON that's cleaner and less error-prone.
The Fix
Replace your requests.post line with this:
headers = { 'Content-type': 'application/json', 'Accept': 'application/json' # Tell the server we want JSON back } response = requests.post(url, json=data, headers=headers)
- Using
json=datainstead ofdata=json.dumps(data)lets Requests automatically convert your dictionary to a valid JSON string and sets the correctContent-Typeheader (no need to do it manually). - Adding
Accept: application/jsonresolves the 406 mismatch by explicitly stating you expect a JSON response from the server.
2. Fixing the simplejson.errors.JSONDecodeError
This error pops up when you try to parse non-JSON content as JSON—most likely the external server is returning an empty response, an HTML error page (like 404 or 500), or plain text instead of valid JSON. Here's how to handle it safely:
What's Going Wrong
Your code calls return response.json() right away, but if the server didn't send valid JSON (e.g., if your request failed), this will throw the decode error. You need to check the response status first and handle invalid JSON gracefully.
The Fix
Add error handling to validate the response before parsing:
print(response.text) # This helps you debug what the server is actually sending try: if response.status_code == 200: return jsonify(response.json()) # Use Flask's jsonify for proper response formatting else: return jsonify( {"error": f"Server returned status code {response.status_code}", "response_content": response.text} ), response.status_code except simplejson.JSONDecodeError: return jsonify( {"error": "Server returned non-JSON response", "response_content": response.text} ), 500
- Always check
response.status_codefirst—200 means the request succeeded; other codes indicate an error. - Wrap
response.json()in a try-except block to catch the decode error if the server sends non-JSON content. - Use Flask's
jsonify()instead of returning a raw dict—it sets the correctContent-Typeheader for Flask responses.
Extra Code Improvements to Avoid Future Headaches
Here are some other tweaks to make your code more reliable:
Use with Statements for File Handling
Manually opening and closing files can lead to leaks if an error occurs. Use with to auto-close files:
# Replace your file write/read code with this data = base64.b64decode(encode) with open("guru99.ics", "wb") as f: f.write(data) with open('guru99.ics', 'rb') as g: gcal = Calendar.from_ical(g.read()) # Process your calendar data here...
Handle Single vs. Multiple Attendees
The ATTENDEE field in iCalendar can be a single value or a list. Your current code will break if it's a single value. Fix it like this:
attend = component.get('ATTENDEE') # Convert single attendee to a list for consistent looping attendees = attend if isinstance(attend, list) else [attend] if attend else [] # Update your data dict to use the processed list data = { # ... other fields ... 'attendee': [elem.split(":", 1)[1] for elem in attendees] }
Don't Return Inside the VEVENT Loop
Right now, you return after processing the first VEVENT—only the first event gets sent to the API. If you want to process all events, move the return outside the loop or collect responses to return together.
内容的提问来源于stack exchange,提问作者Ausy

