Skip to content

Oudwins/zog

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ZOG - A Zod & Yup like Schema Parser & Validator for GO

Coverage Status Go Report Card GitHub tag Go Reference License: MIT

Mentioned in Awesome Go Mentioned in Awesome Templ stars - zog

view - Documentation

Zog is a schema builder for runtime value parsing and validation. Define a schema, transform a value to match, assert the shape of an existing value, or both. Zog schemas are extremely expressive and allow modeling complex, interdependent validations, or value transformations. Checkout the full docs at https://zog.dev

Killer Features:

  • Concise yet expressive schema interface, equipped to model simple to complex data models
  • Zod-like API, use method chaining to build schemas in a typesafe manner
  • Extensible: add your own validators, schemas and data providers
  • Rich error details, make debugging a breeze
  • Almost no reflection when using primitive types
  • Built-in coercion support for most types
  • Zero dependencies!
  • Three Helper Packages
    • zenv: parse environment variables
    • zhttp: parse http forms & query params
    • i18n: Opinionated solution to good i18n zog errors

API Stability:

  • I will consider the API stable when we reach v1.0.0
  • However, I believe very little API changes will happen from the current implementation. The APIs are are most likely to change are the data providers (please don't make your own if possible use the helpers whose APIs will not change meaningfully) and the ParseCtx most other APIs should remain the same
  • Zog will not respect semver until v1.0.0 is released. Expect breaking changes (mainly in non basic apis) until then.

Introduction

0. Read the docs at zog.dev

Or don't, below is the quickstart guide

1 Install

go get github.com/Oudwins/zog

2 Create a user schema and its struct

import (
  z "github.com/Oudwins/zog"
   )


type User struct {
  Name string `zog:"firstname"` // tag is optional. If not set zog will check for "name" field in the input data
  Age int
}

var userSchema = z.Struct(z.Schema{
  // its very important that schema keys like "name" match the struct field name NOT the input data
  "name": z.String().Min(3, z.Message("Override default message")).Max(10),
  "age": z.Int().GT(18).Required(z.Message("is required")),
})

3 Parse into the struct

func main() {
  u := User{}
  m := map[string]string{
    "firstname": "Zog", // Note we are using "firstname" here as specified in the struct tag
    "age": "", // won't return an error because fields are optional by default
  }
  errsMap := schema.Parse(m, &u)
  if errsMap != nil {
    // handle errors -> see Errors section
  }
  u.Name // "Zog"
  // note that this might look weird but we didn't say age was required so Zog just skiped the empty string and we are left with the uninitialized int
  u.Age // 0
}

4. Its easy to use with http

The zhttp package has you covered for JSON, Forms and Query Params, just do:

import (
  zhttp "github.com/Oudwins/zog/zhttp"
   )
err := userSchema.Parse(zhttp.Request(r), &user)

5. Or to validate your environment variables

The zenv package has you covered, just do:

import (
  zenv "github.com/Oudwins/zog/zenv"
   )
err := envSchema.Parse(zenv.NewDataProvider(), &envs)

6. You can also parse individual fields

var t = time.Time
errsList := Time().Required().Parse("2020-01-01T00:00:00Z", &t)

7 And do stuff before and after parsing

var dest []string
Slice(String().Email().Required()).PreTransform(func(data any, ctx z.ParseCtx) (any, error) {
  s := val.(string)
  return strings.Split(s, ","), nil
}).PostTransform(func(destPtr any, ctx z.ParseCtx) error {
  s := val.(*[]string)
  for i, v := range s {
    s[i] = strings.TrimSpace(v)
  }
  return nil
}).Parse("[email protected],[email protected]", &dest) // dest = [[email protected] [email protected]]

Roadmap

These are some of the things I want to add to zog before v1.0.0

  • Support for schema.Clone()
  • support for catch & default for structs & slices
  • Struct generation from the schemas
  • Validate method that will not parse but rather just validate a struct against the schema

Support

The damm domain costs me some outrageous amount like 100$ a year, so if any one wants to help cover that cost through github sponsors that is more than welcome.

Acknowledgments

  • Big thank you to @AlexanderArvidsson for being there to talk about architecture and design decisions. It helped a lot to have someone to bounce ideas off of
  • Credit for all the inspiration goes to /colinhacks/zod & /jquense/yup
  • Credit for the initial idea goes to anthony (@anthonyGG) -> /anthdm/superkit he made a hacky version of this idea that I used as a starting point, I was never happy with it so I inspired me to rewrite it from scratch. I owe him a lot
  • Credit for the zod logo goes to /colinhacks/zod

License

This project is licensed under the MIT License - see the LICENSE file for details.