This is similar to this question, except here the valid arguments are contained in a json file.
In Python using VSCode, I'd like to define a type which is based on the contents of a JSON file. Is such a thing possible?
For example,
data.json
contains data for three object: an_option
, another_option
, and yet_another_option
.
{
"data": [
{
"id":"an_option",
"property":"value"
},
{
"id":"another_option",
"property":"value"
},
{
"id":"yet_another_option",
"property":"value"
}
]
}
In main.py
, I have defined a type that allows Intellisence to suggest these options when writing data of that type. Intellisense suggests my options as parameters when calling test_function
.
from typing import Literal
MyType = Literal[
"an_option",
"another_option",
"yet_another_option"
]
def test_function(option_chosen: MyType):
print(option_chosen)
pass
test_function("an_option")
However, then the names for my options must be replicated in multiple files, which seems cumbersome. I would like the MyType
type to update when I add entries to the data
list from data.json
. For example, something like
from typing import Literal
import json
file = open('data.json', 'r')
data = json.load(file)
list_of_options_with_properties = data["data"]
option_name_list = list()
for option in list_of_options_with_properties:
option_name_list.append(option["id"])
MyType = Literal[tuple(option_name_list)]
def test_function(option_chosen: MyType):
print(option_chosen)
pass
test_function("an_option")
Unfortunately, this does not help autocomplete becuase option_name_list
is not defined until runtime. Is it possible to have Intellisense to read the contents of the json file to define a type?
Directly with Python's type system, this isn't feasible due to the nature of static type checkers operating before code execution. However, you can craft a solution using a code generation tool. You could write a script that reads your JSON file and automatically updates a module with the relevant Literal
type.
# codegen.py
import json
from typing import List
def generate_literal_type_from_json(filename: str) -> List[str]:
with open(filename, 'r') as f:
data = json.load(f)
options = [item["id"] for item in data["data"]]
return options
if __name__ == "__main__":
options = generate_literal_type_from_json("data.json")
with open("generated_types.py", "w") as f:
f.write(f"from typing import Literal\n\n")
f.write(f"MyType = Literal{tuple(options)}\n")
Run this script, and it will produce a generated_types.py
file. You can then use the MyType
type in your main code from this generated file.