Gleam调用HTTP API解析JSON响应失败,示例JSON却正常
问题排查与解决
以下是几种最可能导致解码失败的原因及对应的排查、修复方法:
1. 响应结构不匹配(数组 vs 单个对象)
你手动构造的JSON可能是单个Product对象,但fakestoreapi.com/products返回的是Product对象数组。如果你的解码器是针对单个对象编写的,直接解码数组会失败。
排查方法:
打印API返回的原始响应体:
import gleam/io import http pub fn main() { case http.get("https://fakestoreapi.com/products") { Ok(response) -> io.println(response.body) Err(e) -> io.debug(e) } }
如果输出是[{...}, {...}, ...]格式,说明是数组,需要调整解码器。
修复方法:
将解码器从单个对象改为列表解码器:
import json // 原单个Product解码器 pub fn product_decoder() -> JsonDecoder(Product) { json.decode7(Product, json.int("id"), json.string("title"), json.float("price"), json.string("description"), json.string("category"), json.string("image"), rating_decoder(), ) } // 修改后解码列表 pub fn decode_products(json_str: String) -> Result(List(Product), JsonDecodeError) { json.decode(json_str, json.list(product_decoder())) }
2. 字段名/大小写不匹配
Gleam的JSON解码器默认严格匹配字段名的大小写和拼写。如果API返回的是蛇形命名(比如product_id),而你的自定义类型用的是驼峰(productId),或者字段名拼写有误(比如把rate写成rating),就会解码失败。
排查方法:
对比手动构造的JSON和API返回的字段名,比如API返回的Rating字段是:
"rating": { "rate": 4.5, "count": 100 }
确保你的解码器里用的键名是"rate"和"count",而不是其他拼写。
修复方法:
在解码器中明确指定API返回的字段名,比如:
pub fn rating_decoder() -> JsonDecoder(Rating) { json.decode2(Rating, json.float("rate"), // 严格匹配API返回的键名 json.int("count"), ) }
3. 字段类型/可选性不匹配
API返回的字段可能存在以下情况,导致解码失败:
- 字段值为
null,但你的解码器定义为必填(未用optional包装) - 字段类型与预期不符(比如
price返回字符串"19.99"而非浮点数19.99)
排查方法:
检查API返回的字段类型,比如某条Product的price是否是数字,rating是否始终存在(不会为null)。
修复方法:
- 对可能为
null的字段使用json.optional:
// 如果rating字段可能为null json.optional(rating_decoder(), "rating")
- 对类型不符的字段做转换,比如字符串转浮点数:
json.string("price") |> json.map(fn(s) { float.parse(s) |> result.unwrap(0.0) })
4. 响应体读取不完整或编码错误
极少数情况下,HTTP响应体可能未被完整读取,或者字符编码不匹配(比如API返回UTF-8以外的编码)。
排查方法:
打印响应体的长度,对比手动构造的JSON长度,确认是否完整。
修复方法:
确保使用http.get后正确获取响应体,Gleam的http库默认会完整读取响应体,若仍有问题可尝试手动处理编码:
import gleam/string // 确保响应体是UTF-8编码 let body = string.from_bytes(response.body_bytes, "utf-8") |> result.unwrap("")
内容的提问来源于stack exchange,提问作者jwesonga
相关产品推荐
相关产品推荐

