MedCAT Trainer -- cannot export JSON CUI filter

When trying to download a concerpt filter JSON from the concepts tab I get this error:

[medcattrainer] Internal Server Error: /api/generate-concept-filter-json/
[medcattrainer] Traceback (most recent call last):
[medcattrainer]   File "/home/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner
[medcattrainer]     response = get_response(request)
[medcattrainer]                ^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/home/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response
[medcattrainer]     response = wrapped_callback(request, *callback_args, **callback_kwargs)
[medcattrainer]                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/home/.venv/lib/python3.12/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper
[medcattrainer]     return view_func(request, *args, **kwargs)
[medcattrainer]            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/home/.venv/lib/python3.12/site-packages/django/views/generic/base.py", line 105, in view
[medcattrainer]     return self.dispatch(request, *args, **kwargs)
[medcattrainer]            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/home/.venv/lib/python3.12/site-packages/rest_framework/views.py", line 515, in dispatch
[medcattrainer]     response = self.handle_exception(exc)
[medcattrainer]                ^^^^^^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/home/.venv/lib/python3.12/site-packages/rest_framework/views.py", line 475, in handle_exception
[medcattrainer]     self.raise_uncaught_exception(exc)
[medcattrainer]   File "/home/.venv/lib/python3.12/site-packages/rest_framework/views.py", line 486, in raise_uncaught_exception
[medcattrainer]     raise exc
[medcattrainer]   File "/home/.venv/lib/python3.12/site-packages/rest_framework/views.py", line 512, in dispatch
[medcattrainer]     response = handler(request, *args, **kwargs)
[medcattrainer]                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/home/.venv/lib/python3.12/site-packages/rest_framework/decorators.py", line 50, in handler
[medcattrainer]     return func(*args, **kwargs)
[medcattrainer]            ^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/home/api/api/views.py", line 1076, in generate_concept_filter_flat_json
[medcattrainer]     filter_json = json.dumps(final_filter)
[medcattrainer]                   ^^^^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/usr/local/lib/python3.12/json/__init__.py", line 231, in dumps
[medcattrainer]     return _default_encoder.encode(obj)
[medcattrainer]            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/usr/local/lib/python3.12/json/encoder.py", line 200, in encode
[medcattrainer]     chunks = self.iterencode(o, _one_shot=True)
[medcattrainer]              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/usr/local/lib/python3.12/json/encoder.py", line 258, in iterencode
[medcattrainer]     return _iterencode(o, 0)
[medcattrainer]            ^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/usr/local/lib/python3.12/json/encoder.py", line 180, in default
[medcattrainer]     raise TypeError(f'Object of type {o.__class__.__name__} '
[medcattrainer] TypeError: Object of type dict_keys is not JSON serializable
[medcattrainer] ERROR 2026-05-09 12:49:26,005 log.py l:253:Internal Server Error: /api/generate-concept-filter-json/
[medcattrainer] Traceback (most recent call last):
[medcattrainer]   File "/home/.venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner
[medcattrainer]     response = get_response(request)
[medcattrainer]                ^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/home/.venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response
[medcattrainer]     response = wrapped_callback(request, *callback_args, **callback_kwargs)
[medcattrainer]                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/home/.venv/lib/python3.12/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper
[medcattrainer]     return view_func(request, *args, **kwargs)
[medcattrainer]            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/home/.venv/lib/python3.12/site-packages/django/views/generic/base.py", line 105, in view
[medcattrainer]     return self.dispatch(request, *args, **kwargs)
[medcattrainer]            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/home/.venv/lib/python3.12/site-packages/rest_framework/views.py", line 515, in dispatch
[medcattrainer]     response = self.handle_exception(exc)
[medcattrainer]                ^^^^^^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/home/.venv/lib/python3.12/site-packages/rest_framework/views.py", line 475, in handle_exception
[medcattrainer]     self.raise_uncaught_exception(exc)
[medcattrainer]   File "/home/.venv/lib/python3.12/site-packages/rest_framework/views.py", line 486, in raise_uncaught_exception
[medcattrainer]     raise exc
[medcattrainer]   File "/home/.venv/lib/python3.12/site-packages/rest_framework/views.py", line 512, in dispatch
[medcattrainer]     response = handler(request, *args, **kwargs)
[medcattrainer]                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/home/.venv/lib/python3.12/site-packages/rest_framework/decorators.py", line 50, in handler
[medcattrainer]     return func(*args, **kwargs)
[medcattrainer]            ^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/home/api/api/views.py", line 1076, in generate_concept_filter_flat_json
[medcattrainer]     filter_json = json.dumps(final_filter)
[medcattrainer]                   ^^^^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/usr/local/lib/python3.12/json/__init__.py", line 231, in dumps
[medcattrainer]     return _default_encoder.encode(obj)
[medcattrainer]            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/usr/local/lib/python3.12/json/encoder.py", line 200, in encode
[medcattrainer]     chunks = self.iterencode(o, _one_shot=True)
[medcattrainer]              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/usr/local/lib/python3.12/json/encoder.py", line 258, in iterencode
[medcattrainer]     return _iterencode(o, 0)
[medcattrainer]            ^^^^^^^^^^^^^^^^^
[medcattrainer]   File "/usr/local/lib/python3.12/json/encoder.py", line 180, in default
[medcattrainer]     raise TypeError(f'Object of type {o.__class__.__name__} '
[medcattrainer] TypeError: Object of type dict_keys is not JSON serializable

Root cause: After deduplicating the concept list, final_filter ends up as a dict_keys object (not a plain list). json.dumps() can’t serialise dict_keys, so it crashes.

File: webapp/api/api/views.py line 1086

Before: filter_json = json.dumps(final_filter)

Patch: filter_json = json.dumps(list(final_filter))

Happy to help create pull request if helpful.

Thanks for the feedback!

Yes, this does look like an issue ineed.

And the fix you’ve outlined seems decent as well. So if you don’t mind pushing that as a PR as well, we’d really appreciate it!