Zig语言HTTP请求返回JSON解析失败问题求助
Zig JSON解析错误的修复方案
第一个错误:UnexpectedEndOfInput
你已经通过request.reader().readAllAlloc把响应体全部读到body变量里了,此时请求的数据流已经走到末尾,再用同一个reader创建json_reader解析,自然读不到任何内容,触发这个错误。
修复方法:用已经读取到的body切片创建固定缓冲区流,再基于这个流做解析:
// 用body切片创建流来解析std.json.Value var fbs = std.io.fixedBufferStream(body); var json_reader = std.json.reader(allocator, fbs.reader()); if (std.json.parseFromTokenSource(std.json.Value, allocator, &json_reader, .{})) |json| { defer json.deinit(); std.log.info("json: {any}", .{json.value}); } else |err| { std.log.err("error: {any}", .{err}); }
第二个错误:UnknownField
这个错误有两个核心问题:
问题1:多余的顶层info字段
你打印的响应里的info:是std.log.info的输出前缀,实际返回的JSON根本没有info这个顶层字段,你的Config结构体多套了一层info,这是最关键的错误。
问题2:字段名不匹配+类型错误
- JSON里的
args是空对象{},但你定义成了[]const u8,类型完全不匹配,改成std.json.Value或者空结构体struct {}都可以; - JSON里带连字符的字段(比如
Accept-Encoding、User-Agent),Zig结构体的驼峰命名需要用@jsonName属性指定对应关系。
修正后的Config结构体:
const Config = struct { args: struct {}, // 因为httpbin返回的args永远是空对象,用空结构体更精准 headers: struct { Accept: []const u8, @jsonName("Accept-Encoding") AcceptEncoding: []const u8, Host: []const u8, @jsonName("User-Agent") UserAgent: []const u8, @jsonName("X-Amzn-Trace-Id") XAmznTraceId: []const u8, }, origin: []const u8, url: []const u8, };
完整修正代码
const std = @import("std"); const http = std.http; const Config = struct { args: struct {}, headers: struct { Accept: []const u8, @jsonName("Accept-Encoding") AcceptEncoding: []const u8, Host: []const u8, @jsonName("User-Agent") UserAgent: []const u8, @jsonName("X-Amzn-Trace-Id") XAmznTraceId: []const u8, }, origin: []const u8, url: []const u8, }; pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const allocator = gpa.allocator(); defer _ = gpa.deinit(); // 检查内存泄漏,建议加上 var client = http.Client{ .allocator = allocator }; defer client.deinit(); const uri = try std.Uri.parse("http://httpbin.org/get"); // 不要用unreachable,错误处理更严谨 var headers = std.http.Headers{ .allocator = allocator }; defer headers.deinit(); try headers.append("accept", "*/*,application/json"); // 合并成单个header更规范 var request = try client.request(.GET, uri, headers, .{}); defer request.deinit(); try request.start(); try request.wait(); const body = try request.reader().readAllAlloc(allocator, 8192); defer allocator.free(body); std.log.info("{s}", .{body}); // 解析成std.json.Value var fbs = std.io.fixedBufferStream(body); var json_reader = std.json.reader(allocator, fbs.reader()); if (try std.json.parseFromTokenSource(std.json.Value, allocator, &json_reader, .{})) |json| { defer json.deinit(); std.log.info("json value: {any}", .{json.value}); } // 解析成Config结构体 if (try std.json.parseFromSlice(Config, allocator, body, .{})) |config| { defer config.deinit(); std.log.info("parsed config: {any}", .{config.value}); } }
另外建议把代码里的catch unreachable替换成try或者实际错误处理,避免非预期错误直接导致程序崩溃。
内容的提问来源于stack exchange,提问作者Hasan A Yousef
相关产品推荐
相关产品推荐

