Page MenuHomePhorge

json.zig
No OneTemporary

Size
10 KB
Referenced Files
None
Subscribers
None

json.zig

const std = @import("std");
pub const yyjson = @cImport({
@cInclude("yyjson.h");
});
pub const JsonError = error{
ParseError,
OutOfMemory,
InvalidType,
KeyNotFound,
IoError,
};
pub const JsonDoc = struct {
doc: *yyjson.yyjson_doc,
pub fn parse(data: []const u8) !JsonDoc {
const doc = yyjson.yyjson_read(data.ptr, data.len, 0);
if (doc == null) return error.ParseError;
return JsonDoc{ .doc = doc.? };
}
pub fn parseFile(path: [:0]const u8) !JsonDoc {
const doc = yyjson.yyjson_read_file(path.ptr, 0, null, null);
if (doc == null) return error.ParseError;
return JsonDoc{ .doc = doc.? };
}
pub fn deinit(self: *JsonDoc) void {
yyjson.yyjson_doc_free(self.doc);
}
pub fn root(self: *JsonDoc) JsonValue {
return JsonValue{ .val = yyjson.yyjson_doc_get_root(self.doc).? };
}
};
pub const JsonValue = struct {
val: *yyjson.yyjson_val,
pub fn getString(self: JsonValue, key: [:0]const u8) ?[]const u8 {
const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null;
if (!yyjson.yyjson_is_str(obj)) return null;
const ptr = yyjson.yyjson_get_str(obj) orelse return null;
const len = yyjson.yyjson_get_len(obj);
return ptr[0..len];
}
pub fn getInt(self: JsonValue, key: [:0]const u8) ?i64 {
const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null;
if (!yyjson.yyjson_is_int(obj)) return null;
return yyjson.yyjson_get_sint(obj);
}
pub fn getUint(self: JsonValue, key: [:0]const u8) ?u64 {
const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null;
if (!yyjson.yyjson_is_uint(obj)) return null;
return yyjson.yyjson_get_uint(obj);
}
pub fn getDouble(self: JsonValue, key: [:0]const u8) ?f64 {
const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null;
if (!yyjson.yyjson_is_real(obj)) return null;
return yyjson.yyjson_get_real(obj);
}
pub fn getBool(self: JsonValue, key: [:0]const u8) ?bool {
const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null;
if (!yyjson.yyjson_is_bool(obj)) return null;
return yyjson.yyjson_get_bool(obj);
}
pub fn getObject(self: JsonValue, key: [:0]const u8) ?JsonValue {
const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null;
if (!yyjson.yyjson_is_obj(obj)) return null;
return JsonValue{ .val = obj };
}
pub fn getArray(self: JsonValue, key: [:0]const u8) ?JsonValue {
const obj = yyjson.yyjson_obj_get(self.val, key.ptr) orelse return null;
if (!yyjson.yyjson_is_arr(obj)) return null;
return JsonValue{ .val = obj };
}
pub fn isNull(self: JsonValue) bool {
return yyjson.yyjson_is_null(self.val);
}
pub fn isArray(self: JsonValue) bool {
return yyjson.yyjson_is_arr(self.val);
}
pub fn isObject(self: JsonValue) bool {
return yyjson.yyjson_is_obj(self.val);
}
pub fn arrayLen(self: JsonValue) usize {
return yyjson.yyjson_arr_size(self.val);
}
pub fn arrayGet(self: JsonValue, index: usize) ?JsonValue {
const elem = yyjson.yyjson_arr_get(self.val, index) orelse return null;
return JsonValue{ .val = elem };
}
pub fn asString(self: JsonValue) ?[]const u8 {
if (!yyjson.yyjson_is_str(self.val)) return null;
const ptr = yyjson.yyjson_get_str(self.val) orelse return null;
const len = yyjson.yyjson_get_len(self.val);
return ptr[0..len];
}
pub const ObjectIterator = struct {
iter: yyjson.yyjson_obj_iter,
pub fn next(self: *ObjectIterator) ?struct { key: []const u8, value: JsonValue } {
const key_val = yyjson.yyjson_obj_iter_next(&self.iter) orelse return null;
const val = yyjson.yyjson_obj_iter_get_val(key_val) orelse return null;
const key_ptr = yyjson.yyjson_get_str(key_val) orelse return null;
const key_len = yyjson.yyjson_get_len(key_val);
return .{
.key = key_ptr[0..key_len],
.value = JsonValue{ .val = val },
};
}
pub fn deinit(_: *ObjectIterator) void {}
};
pub fn objectIterator(self: JsonValue) ?ObjectIterator {
if (!yyjson.yyjson_is_obj(self.val)) return null;
var iter: yyjson.yyjson_obj_iter = undefined;
if (!yyjson.yyjson_obj_iter_init(self.val, &iter)) return null;
return ObjectIterator{ .iter = iter };
}
pub const ArrayIterator = struct {
iter: yyjson.yyjson_arr_iter,
pub fn next(self: *ArrayIterator) ?JsonValue {
const val = yyjson.yyjson_arr_iter_next(&self.iter) orelse return null;
return JsonValue{ .val = val };
}
pub fn deinit(_: *ArrayIterator) void {}
};
pub fn arrayIterator(self: JsonValue) ?ArrayIterator {
if (!yyjson.yyjson_is_arr(self.val)) return null;
var iter: yyjson.yyjson_arr_iter = undefined;
if (!yyjson.yyjson_arr_iter_init(self.val, &iter)) return null;
return ArrayIterator{ .iter = iter };
}
};
pub const JsonWriter = struct {
doc: *yyjson.yyjson_mut_doc,
pub fn init() !JsonWriter {
const doc = yyjson.yyjson_mut_doc_new(null);
if (doc == null) return error.OutOfMemory;
return JsonWriter{ .doc = doc.? };
}
pub fn deinit(self: *JsonWriter) void {
yyjson.yyjson_mut_doc_free(self.doc);
}
pub fn createObject(self: *JsonWriter) *yyjson.yyjson_mut_val {
return yyjson.yyjson_mut_obj(self.doc).?;
}
pub fn createArray(self: *JsonWriter) *yyjson.yyjson_mut_val {
return yyjson.yyjson_mut_arr(self.doc).?;
}
pub fn createString(self: *JsonWriter, str: []const u8) *yyjson.yyjson_mut_val {
return yyjson.yyjson_mut_strncpy(self.doc, str.ptr, str.len).?;
}
pub fn createInt(self: *JsonWriter, val: i64) *yyjson.yyjson_mut_val {
return yyjson.yyjson_mut_sint(self.doc, val).?;
}
pub fn createUint(self: *JsonWriter, val: u64) *yyjson.yyjson_mut_val {
return yyjson.yyjson_mut_uint(self.doc, val).?;
}
pub fn createBool(self: *JsonWriter, val: bool) *yyjson.yyjson_mut_val {
return yyjson.yyjson_mut_bool(self.doc, val).?;
}
pub fn createReal(self: *JsonWriter, val: f64) *yyjson.yyjson_mut_val {
return yyjson.yyjson_mut_real(self.doc, val).?;
}
pub fn createNull(self: *JsonWriter) *yyjson.yyjson_mut_val {
return yyjson.yyjson_mut_null(self.doc).?;
}
pub fn objectAdd(self: *JsonWriter, obj: *yyjson.yyjson_mut_val, key: []const u8, val: *yyjson.yyjson_mut_val) void {
const key_val = yyjson.yyjson_mut_strncpy(self.doc, key.ptr, key.len);
_ = yyjson.yyjson_mut_obj_add(obj, key_val, val);
}
pub fn arrayAppend(_: *JsonWriter, arr: *yyjson.yyjson_mut_val, val: *yyjson.yyjson_mut_val) void {
_ = yyjson.yyjson_mut_arr_append(arr, val);
}
pub fn setRoot(self: *JsonWriter, val: *yyjson.yyjson_mut_val) void {
yyjson.yyjson_mut_doc_set_root(self.doc, val);
}
pub fn write(self: *JsonWriter, allocator: std.mem.Allocator) ![]u8 {
var len: usize = 0;
const ptr = yyjson.yyjson_mut_write(self.doc, yyjson.YYJSON_WRITE_PRETTY_TWO_SPACES, &len);
if (ptr == null) return error.OutOfMemory;
defer std.c.free(ptr);
const result = try allocator.alloc(u8, len);
@memcpy(result, ptr[0..len]);
return result;
}
pub fn writeToFile(self: *JsonWriter, path: [:0]const u8) !void {
const success = yyjson.yyjson_mut_write_file(path.ptr, self.doc, yyjson.YYJSON_WRITE_PRETTY_TWO_SPACES, null, null);
if (!success) return error.IoError;
}
};
pub const PackageJson = struct {
name: []const u8,
version: []const u8,
dependencies: std.StringHashMap([]const u8),
dev_dependencies: std.StringHashMap([]const u8),
peer_dependencies: std.StringHashMap([]const u8),
optional_dependencies: std.StringHashMap([]const u8),
trusted_dependencies: std.StringHashMap(void),
pub fn parse(allocator: std.mem.Allocator, path: [:0]const u8) !PackageJson {
var doc = try JsonDoc.parseFile(path);
defer doc.deinit();
const root_val = doc.root();
var pkg = PackageJson{
.name = "",
.version = "",
.dependencies = std.StringHashMap([]const u8).init(allocator),
.dev_dependencies = std.StringHashMap([]const u8).init(allocator),
.peer_dependencies = std.StringHashMap([]const u8).init(allocator),
.optional_dependencies = std.StringHashMap([]const u8).init(allocator),
.trusted_dependencies = std.StringHashMap(void).init(allocator),
};
if (root_val.getString("name")) |s| {
pkg.name = try allocator.dupe(u8, s);
}
if (root_val.getString("version")) |s| {
pkg.version = try allocator.dupe(u8, s);
}
try parseDeps(allocator, root_val, "dependencies", &pkg.dependencies);
try parseDeps(allocator, root_val, "devDependencies", &pkg.dev_dependencies);
try parseDeps(allocator, root_val, "peerDependencies", &pkg.peer_dependencies);
try parseDeps(allocator, root_val, "optionalDependencies", &pkg.optional_dependencies);
if (root_val.getArray("trustedDependencies")) |arr| {
for (0..arr.arrayLen()) |i| {
const name = (arr.arrayGet(i) orelse continue).asString() orelse continue;
try pkg.trusted_dependencies.put(try allocator.dupe(u8, name), {});
}
}
return pkg;
}
fn parseDeps(
allocator: std.mem.Allocator,
root_val: JsonValue,
key: [:0]const u8,
map: *std.StringHashMap([]const u8),
) !void {
if (root_val.getObject(key)) |deps| {
var iter = deps.objectIterator() orelse return;
defer iter.deinit();
while (iter.next()) |entry| {
const version = entry.value.asString() orelse continue;
try map.put(try allocator.dupe(u8, entry.key), try allocator.dupe(u8, version));
}
}
}
pub fn deinit(self: *PackageJson, allocator: std.mem.Allocator) void {
if (self.name.len > 0) allocator.free(self.name);
if (self.version.len > 0) allocator.free(self.version);
var iter = self.dependencies.iterator();
while (iter.next()) |entry| {
allocator.free(entry.key_ptr.*);
allocator.free(entry.value_ptr.*);
}
self.dependencies.deinit();
iter = self.dev_dependencies.iterator();
while (iter.next()) |entry| {
allocator.free(entry.key_ptr.*);
allocator.free(entry.value_ptr.*);
}
self.dev_dependencies.deinit();
iter = self.peer_dependencies.iterator();
while (iter.next()) |entry| {
allocator.free(entry.key_ptr.*);
allocator.free(entry.value_ptr.*);
}
self.peer_dependencies.deinit();
iter = self.optional_dependencies.iterator();
while (iter.next()) |entry| {
allocator.free(entry.key_ptr.*);
allocator.free(entry.value_ptr.*);
}
self.optional_dependencies.deinit();
var trusted_iter = self.trusted_dependencies.keyIterator();
while (trusted_iter.next()) |key| {
allocator.free(key.*);
}
self.trusted_dependencies.deinit();
}
};

File Metadata

Mime Type
text/plain
Expires
Sun, May 3, 7:32 AM (15 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
537948
Default Alt Text
json.zig (10 KB)

Event Timeline