一次线上服务器500错误排查记录: TypeError: Object of type NAType is not JSON serial

  1. 查看服务器日志看到错误:TypeError: Object of type NAType is not JSON serializable,从字面可以看到大约是NATYPE类型的数据序列化出错。

  2. chatgpt查了下这个错误,解释:

这个错误表明在尝试将某个对象序列化为 JSON 格式时,遇到了无法被 JSON 序列化的对象类型,具体来说是 NAType 对象。NAType 通常表示 Pandas 中的缺失值(Not a Type)。

  1. 那错误原因就很明显了

接口返回时可能是由于某个地方返回了包含 Pandas DataFrame 或 Series 的数据结构,而其中包含了 Pandas 的 pd.NA 缺失值,而 JSON 序列化操作无法处理这种对象。

  1. 然后取查看代码,找到pd处理的地方。

     ……
       query_sql = text("""
                          select name, 
                          json_unquote(json_extract(detail, '$.t1')) as t1,
                          json_unquote(json_extract(detail, '$.t2')) as t2,
                          from `test` where id = :id;
                      """)
       ……
       if 't1' in data_df.columns:
           data_df['t1'] = data_df['t1'].fillna(np.nan)
           data_df['t1'] = data_df['t1'].astype(pd.Int64Dtype())
       if 't2' in data_df.columns:
           data_df['t2'] = data_df['t2'].fillna(np.nan)
           data_df['t2'] = data_df['t2'].astype(pd.Int64Dtype())
       ……
       content = data_df.to_dict(orient='records')[0]
       return Response(data={
           ……
           'content':content
       })
    
  2. 代码初衷

  3. 库里json字段的t1/t2类型是数值类型或者为空。但是pd从库里读到的t1/t2字段在df表现是string类型,还可能是None。

  4. 返回需求是int类型,由于直接用astype因为None缘故会报错。所以用了fillna和pd.Int64Dtype。
  5. 如此就可以将包含None的string类型的字段转为int类型。(后来意识到应该是Int64类型)
  6. 此时为空的应是np.nan类型,表现上是None(……)。然后转为字典返回前端。

  7. 修改,那就换一种方式

    data_df['t1'] = data_df['t1'].apply( lambda x: int(x) if isinstance(x, str) else x)

  8. 备注:

    • 在开发环境用接口软件测试是原先的转换方法是可以的,不报错。
    • 在生产环境原先的转换方法报错,修改可以了。
  9. 疑惑:原因知道了,但是不理解。为什么我用接口测试软件测试正常,但是到了线上出错……


发表评论

评论列表,共 0 条评论

    暂无评论