Std.json parse array of strings

Here is some json

 {
     "sort_method": 1,
     "duration": 60,
     "uris": [
         "/"
     ]
}

I’m having trouble figuring out how to use std.json to parse an array of strings uris.
I’d like to do something like.

const configuration_data = try std.fs.cwd().readFileAlloc(base_allocator, uri_list.items, 1000000);
defer base_allocator.free(configuration_data);
const config_parsed = try std.json.parseFromSlice(types.Configuration, base_allocator, configuration_data, .{ .allocate = .alloc_always });
defer config_parsed.deinit();

config.duration = config_parsed.value.duration;
config.uris = config_parsed.value.uris;
config.sort_method = config_parsed.value.sort_method;

I’ve been trying to figure out how to acheive this parsing into a struct.
Here is the struct.

pub const Configuration = struct {
    sort_method: SORT_METHOD = SORT_METHOD.singleSegment,
    duration: ?f32 = null,
    uris: std.ArrayListUnmanaged([]const u8),  // I just tried ArrayListUnmanaged, but I've tried a bunch of types.
};

I can’t quite get this to work. I know this has to be a solved problem does anyone know the proper way to do this?

Much obliged.

To parse an array of T you need a slice []T. For a slice of strings: uris: [][]const u8
Example:

const std = @import("std");

const Conf = struct {
    uris: [][]const u8,
};

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const json =
        \\{
        \\  "uris": [
        \\      "/"
        \\  ]
        \\}
    ;
    const parsed = try std.json.parseFromSlice(Conf, gpa.allocator(), json, .{});
    defer parsed.deinit();
    std.debug.print("{any}\n", .{parsed.value});
}
2 Likes

You beat me to it. Anyway for what it is worth. Here is what I came up with.

JSON file

changed your json to the below.

cat my.json
{
     "sort_method": 1,
     "duration": 60,
     "uris": [
         "/", "*"
     ]
}

Code

 pub fn main() !void {

    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    // What is the current directory we are in
    std.debug.print("pwd: {s}\n", .{ try std.fs.cwd().realpathAlloc(allocator, "."), });


    const parsed = try readJson(allocator, "my.json");
    defer parsed.deinit();

    const config = parsed.value;

    std.debug.print("{d}\n", .{config.sort_method});
    std.debug.print("{d}\n", .{config.duration});
    std.debug.print("{s}\n", .{config.uris[0][0..]});
    std.debug.print("{s}\n", .{config.uris[1][0..]}); // added a field
}

fn readJson(allocator: Allocator, file_name: []const u8) !std.json.Parsed(My_output) {

  // 1024 if your config is larger .....
  const data = try std.fs.cwd().readFileAlloc(allocator, file_name, 1024);
  defer allocator.free(data);

  //  std.debug.print("{s}\n", .{data});
  return std.json.parseFromSlice(My_output, allocator, data, .{.allocate = .alloc_always});
}

// has to have all the names of data
const My_output = struct { sort_method: u32, duration: u32, uris: [][]const u8 };

//"sort_method": 1,
//"duration": 60,
//"uris": [
//    "/","*"
//]
//

zig version
0.13.0-dev.211+6a65561e3

1 Like