Как перевести словарь значений NumPy int64 в JSON?

Имею некоторую массу вычислений, основанных на типах данных NumPy и Pandas.

y_true = np.where(true_birads >= birads_thresh, 1, 0)
y_pred = np.where(pred_birads >= birads_thresh, 1, 0)

birads_metrics["Accuracy"] = str(metrics.accuracy_score(true_birads, pred_birads))
birads_metrics["F1-Macro"] = str(metrics.f1_score(true_birads, pred_birads, average="macro"))
f_class = metrics.fbeta_score(true_birads, pred_birads, beta=1.5, average=None)
#birads_metrics["F-weighted"] = np.sum(np.multiply(f_class, weights)) / np.sum(weights)
tn, fp, fn, tp = metrics.confusion_matrix(y_true, y_pred).ravel()
birads_metrics['Confusion Matrix'] = {'TN': str(tn), 'FP': str(fp), 'FN': str(fn), 'TP': str(tp)}
birads_metrics["Specificity"] = tn / (tn + fp)
birads_metrics["Recall"] = metrics.recall_score(y_true, y_pred)
birads_metrics["PPV"] = str(tp / (tp + fp))
birads_metrics["NPV"] = str(tn / (tn + fn))
birads_metrics["PPR"] = str(birads_metrics["Recall"] / (1 - birads_metrics["Specificity"]))
birads_metrics["NPR"] = str((1 - birads_metrics["Recall"]) / birads_metrics["Specificity"])
birads_metrics["Recall"] = str(birads_metrics["Recall"])
birads_metrics["Specificity"] = str(birads_metrics["Specificity"])

Задача - сконвертировать словарь birads_metrics в JSON для последующей отправки в jsonb-столбец postgresql через requests и API на Django Rest Farmework.

Проблема: значения numpy in64 не конвертируются в JSON функцией json.dumps(), попытка вручную сформировать строку, идентичную json, приводит к ругани от DRF на некорректность формата json. Как видно из кода, преобразование всех значений в строку даёт нужный результат и всё работает отлично. Так же пробовал кастомный класс json.JSONEncoder, но нужного результата это не принесло. Текущий вариант со строками выглядит просто ужасно. Посоветуйте, как можно поступить в данной ситуации для автоматизированного преобразования в строки.

class NpEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, np.integer):
            return int(obj)
        elif isinstance(obj, np.floating):
            return float(obj)
        elif isinstance(obj, np.ndarray):
            return str(obj.tolist())
        else:
            return super(NpEncoder, self).default(obj)

Ответы (2 шт):

Автор решения: MaxU

Воспользуйтесь функцией DataFrame.to_json():

import json
df = pd.DataFrame(
    [["a", "b"], ["c", "d"]],
    index=["row 1", "row 2"],
    columns=["col 1", "col 2"],
)
result = df.to_json(orient="split")
parsed = json.loads(result)

результат:

>>>json.dumps(parsed, indent=4)  
{
    "columns": [
        "col 1",
        "col 2"
    ],
    "index": [
        "row 1",
        "row 2"
    ],
    "data": [
        [
            "a",
            "b"
        ],
        [
            "c",
            "d"
        ]
    ]
}

→ Ссылка
Автор решения: UlisPaxton

Решение похоже найдено. Был изменен класс JSONEncoder.

class NpEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, np.float64):
            return float(obj)
        elif isinstance(obj, np.int64):
            return int(obj)
        return str(obj)
result_json = json.dumps(birads_metrics, cls=NpEncoder)

Это решение помогло.

→ Ссылка