Add custom marshaler/unmarshaler interface support

Summary

Allow types to customize their JSON serialization/deserialization by implementing interface methods.

Background

Go provides Marshaler, MarshalerTo, Unmarshaler, UnmarshalerFrom interfaces for type-specific customization.

Proposed API

/// Types implementing this can customize JSON encoding
pub const Marshaler = struct {
    marshalJsonFn: *const fn (self: anytype, writer: anytype) anyerror!void,
};

/// Types implementing this can customize JSON decoding  
pub const Unmarshaler = struct {
    unmarshalJsonFn: *const fn (self: *anytype, value: Value) anyerror!void,
};

// Detection via @hasDecl
// If type has `pub fn marshalJson(self: @This(), writer: anytype) !void`
// the encoder will call it instead of default behavior

// Example usage:
const CustomDate = struct {
    year: u16,
    month: u8,
    day: u8,
    
    pub fn marshalJson(self: CustomDate, writer: anytype) !void {
        try writer.print("\"{d:0>4}-{d:0>2}-{d:0>2}\"", .{self.year, self.month, self.day});
    }
    
    pub fn unmarshalJson(self: *CustomDate, value: Value) !void {
        // Parse "YYYY-MM-DD" string
    }
};

Features

  • Detect marshalJson method at comptime
  • Detect unmarshalJson method at comptime
  • Support both writer-based and Value-based interfaces
  • Caller-specified custom marshalers (like Go's WithMarshalers)
  • Support for external types that can't be modified

Reference

Go: Marshaler, MarshalerTo, Unmarshaler, UnmarshalerFrom, WithMarshalers(), WithUnmarshalers()

Priority

High - Essential for real-world usage