Julia Genie路由报unexpected end of input错误求助
问题描述
######################### ERROR STACKTRACE #########################
Expected end of input
Line: 0
Around: ...11092×16 DataFrame Row...
使用Julia的Genie框架编写路由时触发上述错误,但将路由内的代码单独在终端运行时,可正常生成包含证券标的信息的DataFrame。目标是将/tickers作为API后端,/send用于桌面应用调用。
原代码如下:
using Genie, Genie.Renderer.Json, Genie.Requests using HTTP, JSON using DataFrames route("/tickers", method = POST) do message = jsonpayload() # (:echo => (message["message"] * " ") ^ message["repeat"]) |> json syms = HTTP.request("GET","https://acre.iex.cloud/v1/data/CORE/REF_DATA?token=pk_79891f5cbcce4099ae063588956f937a") schema_req = HTTP.request("GET","https://acre.iex.cloud/v1/data/CORE/REF_DATA?schema=true&token=pk_79891f5cbcce4099ae063588956f937a") sbs = syms.body |> String |> JSON.parse smat = sbs .|> values .|> collect |> (x->reduce(hcat,x)) |> (x->permutedims(DataFrame(x,:auto))) schema = schema_req.body |> String |> JSON.parse |> first |> keys |> collect rename!(smat,Symbol.(schema)) end route("/send") do response = HTTP.request("POST", "http://localhost:8000/tickers", [("Content-Type", "application/json")], """{"exchanges":"XNYS", "type":"cs"}""") response.body |> String |> JSON.parse end up(async = false)
解决方案
- 核心错误原因:Genie路由处理函数必须返回可被HTTP响应序列化的内容,当前
/tickers路由最后返回的是DataFrame对象,Genie无法直接将其转换为合法的HTTP响应体,导致解析出错。 - 修复步骤:
- 在
/tickers路由末尾,将DataFrame转换为JSON格式返回,使用Genie提供的json()函数完成序列化。 - 利用请求传入的
exchanges和type参数,给API请求添加过滤条件,避免获取全量数据(原代码未使用传入参数,全量数据会增大响应体积)。 - 合并两次API请求为一次,直接从返回数据的第一个元素提取列名,减少冗余请求。
- 在
修改后的代码示例:
using Genie, Genie.Renderer.Json, Genie.Requests using HTTP, JSON using DataFrames route("/tickers", method = POST) do # 获取请求参数,设置默认值避免参数缺失 payload = jsonpayload() exchanges = get(payload, "exchanges", "") ticker_type = get(payload, "type", "") # 构造带过滤条件的API请求URL api_token = "pk_79891f5cbcce4099ae063588956f937a" query_params = Dict( "token" => api_token, "exchanges" => exchanges, "type" => ticker_type ) # 拼接非空的查询参数 query_str = join(["$k=$v" for (k,v) in query_params if !isempty(v)], "&") api_url = "https://acre.iex.cloud/v1/data/CORE/REF_DATA?$query_str" # 调用API并处理数据 syms_response = HTTP.request("GET", api_url) sbs = syms_response.body |> String |> JSON.parse if !isempty(sbs) # 直接从返回数据提取列名并构造DataFrame df = DataFrame(sbs) # 返回JSON格式响应,自动设置正确的Content-Type头 return json(df) else # 返回空数据的兜底响应 return json(Dict("data" => [])) end end route("/send") do response = HTTP.request("POST", "http://localhost:8000/tickers", [("Content-Type", "application/json")], """{"exchanges":"XNYS", "type":"cs"}""") # 将响应转换为JSON格式返回 return json(response.body |> String |> JSON.parse) end up(async = false)
- 额外说明:
json()函数是Genie的响应渲染工具,会自动处理序列化和HTTP头设置,确保客户端能正确解析。- 新增参数默认值,避免请求参数缺失时API调用出错。
- 移除了单独请求schema的逻辑,直接从返回数据提取列名,提升效率。
内容的提问来源于stack exchange,提问作者Ethan Leonard
相关产品推荐
相关产品推荐

