21

Consider:

import logging
import azure.functions as func

def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    name = {"test":"jjj"}
    return func.HttpResponse(name)

Above is my Azure function (V2) using Python preview.

If I return

func.HttpResponse(f"{name}")

it works, but if I return a dict object it does not.

The error displayed is:

Exception: TypeError: reponse is expected to be either of str, bytes, or bytearray, got dict

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
maswadkar
  • 1,502
  • 1
  • 13
  • 23

6 Answers6

44

You need to convert your dictionary to a JSON string using the built-in JSON library - json.dumps.

Then you can set the MIME type (Content-Type) of your function to application/json. By default Azure functions HttpResponse returns text/plain Content-Type.

import json
import logging
import azure.functions as func

def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    name = {"test":"jjj"}
    return func.HttpResponse(
        json.dumps(name),
        mimetype="application/json",
    )
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
brandonbanks
  • 1,125
  • 1
  • 14
  • 21
9

Better way:

func.HttpResponse.mimetype = 'application/json'
func.HttpResponse.charset = 'utf-8'

return func.HttpResponse(json_object)
סטנלי גרונן
  • 2,917
  • 23
  • 46
  • 68
Fremin Abreu
  • 129
  • 1
  • 4
  • Could you elaborate why this is better? It looks like this is modifying global variables in a foreign module, which is an ugly side effect. Also, I'm simply getting a (runtime) `TypeError` if I don't serialize the `json_object` myself. And type checking the code with mypy/pyright fails, because the first argument to `HttpResponse` is typed as `str | bytes`, so you cannot just pass in your raw data, right? Also, specifying the charset as `utf-8` is redundant, because it is the default anyway. – bluenote10 Jan 18 '23 at 15:18
1

First of all, I am not a Python expert. I am just trying to let you know what the issue is all about.

So on Azure function if you look, it would seem its return type is IActionResult. If you decompile it, you would see:

IActionResult IConvertToActionResult.Convert()
    {
      ActionResult result = this.Result;
      if (result != null)
        return (IActionResult) result;
      return (IActionResult) new ObjectResult((object) this.Value)
      {
        DeclaredType = typeof (TValue)
      };
    }

So it expects an object from you rather than a Dictionary or List or any kind of generics type. But if you convert it into an object like OkObjectResult, you wouldn't encounter any compile error. See the example below:

IDictionary<int, string> MyDictionary = new Dictionary<int, string>();
MyDictionary.Add(new KeyValuePair<int, string>(1, "One"));
MyDictionary.Add(new KeyValuePair<int, string>(2, "Two"));

// As we have to return IAction Type, so converting to IAction class
// using OkObjectResult we can even use OkResult
return new MyDictionary;

The above code would encounter your compile error. Because it does not support Dictionary or List Or any generic directly. See the screenshot below:

Enter image description here

See what the error said:

Enter image description here

But if you convert your Dictionary or List Or any generic into an object type, it will resolve your issue for sure. See the below example:

IDictionary<int, string> MyDictionary = new Dictionary<int, string>();
MyDictionary.Add(new KeyValuePair<int, string>(1, "One"));
MyDictionary.Add(new KeyValuePair<int, string>(2, "Two"));

// So have converted MyDictionary into Object type that the compiler deserve. And no compile error encountered.
return new OkObjectResult(MyDictionary);

See the screenshot below:

Enter image description here

Note: If you try to parse your func.HttpResponse(name) into an object then finally return, your problem should resolve. So you can try to add a reference to this package in your project (import json) and try the below code:

import json

name = {"test":"jjj"}

print(json.dumps(name))
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Md Farid Uddin Kiron
  • 16,817
  • 3
  • 17
  • 43
1

The proper way to do this is:

return func.HttpResponse(
   body = name,
   status_code = 200
)

See the documentation for more information on the HttpResponse class.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
adrien
  • 504
  • 1
  • 7
  • 17
  • 2
    This is not the solution and raises the same exception as the original post. `Exception: TypeError: reponse is expected to be either of str, bytes, or bytearray, got dict` – brandonbanks Jan 13 '20 at 15:47
  • right, the api might have changed, I should have mentioned which version this was for. – adrien Jan 15 '20 at 11:38
0

Try it like this:

 import json

     return func.HttpResponse (
        json.dumps({
        'lat': lat,
        'lon': lon

        })
     )
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Manoj Alwis
  • 1,337
  • 11
  • 24
  • That is not valid Python by itself (indentation). Is it only a snippet? Can you [elaborate](https://stackoverflow.com/posts/68552786/edit) in your answer? – Peter Mortensen Sep 30 '21 at 11:42
0

what about this, create a json object (json dumps creates a json from a dictonary) and return that in the body of your response:

# json object
result = {
    "arg1" : variable1,
    "arg2" : variable2
}
result = json.dumps(result, indent = 4) 

return func.HttpResponse(
        body = result,
        status_code=200
)
Ewald Bos
  • 1,560
  • 1
  • 20
  • 33