Skip to content

Announcing Getty 0.2.0

I am happy to announce a new version of Getty, 0.2.0. 🎉

Getty is a framework for building robust, optimal, and reusable serializers/deserializers in Zig. To install Getty, follow the instructions listed on the Installation page.

What's in 0.2.0

Revamped Interfaces

Thanks to stage2, there were lots of improvements made to the interfaces in Getty. Most notably:

  • Required method parameters are now optional struct fields, making implementing interfaces much simpler.
  • Most associated types have been made optional, so no more getty.TODO.
  • Empty error sets are now allowed.
  • No more relying on undefined errors to indicate that a unimplemented method was called. Getty can now have @compileErrors in its interfaces to let you know about that.
Zig code
const Serializer = struct {
    pub usingnamespace Serializer(
        @This(),
        void,
        error{},
        null,
        null,
        null,
        null,
        null,
        .{ .serializeBool = serializeBool },
    );
};

Simpler Customization

On the customization side of things, two main features have been added.

First, you can now write type-defined blocks/tuples (TBT), which are (de)serialization blocks/tuples defined within a struct or union type. Getty will automatically process TBTs, meaning that you don't have to pass them in explicitly.

Second, preliminary support for attributes have landed. Attributes allow you to easily configure the (de)serialization process for a type without having to manually write everything out. This release introduced support only for the skip, rename, and ignore_unknown_fields attributes.

Zig code
const std = @import("std");
const json = @import("json");

const allocator = std.heap.page_allocator;

const Point = struct {
    x: i32,
    y: i32,

    pub const @"getty.sbt" = struct {
        pub fn is(comptime T: type) bool {
            return T == Point;
        }

        pub const attributes = .{
            .x = .{ .rename = "X" },
            .y = .{ .skip = true },
        };
    };
};

pub fn main() !void {
    _ = try json.toSlice(allocator, Point{ .x = 1, .y = 2 }); // {"X":1}
}

Union Serialization

Before, unions were serialized as their payload value. However, this made things inconsistent as there was no good way to go back during deserialization with that approach.

To fix this, unions are now serialized using the externally tagged format by default.

Zig code
const std = @import("std");
const getty = @import("getty");
const json = @import("json");

const allocator = std.heap.page_allocator;

pub fn main() !void {
    const U = union(enum) { foo: i32 };

    var slice = try json.toSlice(allocator, U{ .foo = 123 });
    defer allocator.free(slice);

    std.debug.print("{s}\n", .{slice}); // {"foo":123}
}

Ignoring Deserialized Data

A new method has been added to the getty.Deserializer interface: deserializeIgnored. This method is intended to be used whenever the input data of a deserializer should be ignored. For example, when the skip attribute is set for a struct, deserializeIgnored can be called in order to ignore a key and/or value in the deserializer's input data.

Support

Some new types are now supported by Getty!

Serialization
Deserialization
  • Union (tagged)
  • Union (untagged)
  • Sentinel-terminated slice

Other Changes

There are other changes in the Getty 0.2.0 release. You can see the full changelog here.