How do I type annotate JSON data in Python?

Viewed 4733

I am adding type annotations to a lot of code to make it clear to other devs what my functions and methods do. How would I type annotate a function that takes JSON data in as an argument, and returns JSON data?

(very simplified version)

def func(json_data):
    return json_data

what I want to do but with JSON instead of int:

def add_nums(a: int, b: int) -> int:
    return a+b
2 Answers

You can not do that. There are no "json objects" in python. Json is represented as a string. The most correct answer here would be:

def func(json_data: str) -> str:
    return json_data

In my opinion (I also think it is best practice but not sure about that) you should only convert your data to json when you really need it in that format. Before that you should always be working with dictionaries and lists.

Json objects are usually like a bag of items. It can have numbers, string, floats, list and nested json objects. If you wish to deep dive into JSON body actual structure then following Option1 & 2 can assist you or you can do the 3 rd step.

First Option: Please check this Python3 docs links.

If you can clearly define your json body then you can use following example.

from collections.abc import Sequence

ConnectionOptions = dict[str, str]
Address = tuple[str, int]
Server = tuple[Address, ConnectionOptions]

def broadcast_message(message: str, servers: Sequence[Server]) -> None:
    ...

# The static type checker will treat the previous type signature as
# being exactly equivalent to this one.
def broadcast_message(
        message: str,
        servers: Sequence[tuple[tuple[str, int], dict[str, str]]]) -> None:
    ...

Second Option: you can also define you own custom type classes to work with, unlike above where you create lots of global items.

https://docs.python.org/3/library/typing.html#newtype


from typing import NewType

UserId = NewType('UserId', int)
some_id = UserId(524313)

def get_user_name(user_id: UserId) -> str:
    ...

Third Option: Like the above suggested answers, using a str is simple approach. Treat you json body as string and using json modules to convert it to string & viceversa

Fourth Option: Using a Library to define your classes - https://marshmallow.readthedocs.io/en/stable/

If you are working on Apache Spark then https://github.com/ketgo/marshmallow-pyspark is worth knowing about.

Related