You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 23:47:02