A Go package that provides custom database fields and JSON-friendly types
- Go 100%
| currency.go | ||
| decimal.go | ||
| dimension.go | ||
| email.go | ||
| file.go | ||
| geo_location.go | ||
| go.mod | ||
| go.sum | ||
| json.go | ||
| password.go | ||
| phone.go | ||
| README.md | ||
| string_array.go | ||
| time.go | ||
anar-types
A Go package that provides custom database fields and JSON-friendly types for common application needs.
These fields integrate smoothly with GORM, the database/sql driver, and standard Go encoding/json.
Features
- FileField Expands relative paths into full URLs using
APP_URLenv variable. - JSONField Stores
map[string]interface{}as JSON in DB. - StringArray Stores
[]stringas JSON in DB. - TimeField Nullable timestamp with ISO8601 (RFC3339) JSON serialization.
- EmailField RFC5322-compliant email validation and safe DB storage.
- PhoneField Validated phone numbers in E.164 format using
libphonenumber. - GeoLocationField Latitude, longitude, and optional altitude with validation.
- DimensionField Width, height, depth, and unit (cm, m, in, ft).
- CurrencyField Money values with ISO4217 currency validation.
- PasswordField Secure password storage with bcrypt hashing, strength validation, JSON masking, and comparison helpers.
- Decimal High-precision fixed-point decimal with math operations, rounding, JSON/DB integration, and string/float conversions.
Installation
go get codeberg.org/anarproject/anar-types
Usage
FileField
type User struct {
Avatar types.FileField `json:"avatar"`
}
// If APP_URL="https://example.com"
// and Avatar="uploads/img.png"
// JSON ? { "avatar": "https://example.com/uploads/img.png" }
JSONField
type Settings struct {
Config types.JSONField `json:"config"`
}
settings := Settings{
Config: types.JSONField{"theme": "dark", "lang": "en"},
}
StringArray
type Post struct {
Tags types.StringArray `json:"tags"`
}
post := Post{Tags: []string{"go", "gorm", "json"}}
TimeField
now := time.Now()
t := types.NewTimeField(now)
jsonBytes, _ := json.Marshal(t)
// ? "2025-09-29T04:00:00Z"
EmailField
var email types.EmailField
email.Scan("user@example.com") // ? valid
email.Scan("bad-email") // ? error
PhoneField
var phone types.PhoneField
_ = phone.UnmarshalJSON([]byte(`"+14155552671"`))
// phone ? "+14155552671"
fmt.Println(phone.National()) // (415) 555-2671
fmt.Println(phone.Region()) // US
GeoLocationField
geo := types.GeoLocationField{
Latitude: 37.7749,
Longitude: -122.4194,
Altitude: 15.5,
}
jsonBytes, _ := json.Marshal(geo)
// ? {"lat":37.7749,"lng":-122.4194,"alt":15.5}
DimensionField
dim := types.DimensionField{
Width: 100,
Height: 200,
Depth: 50,
Unit: "cm",
}
jsonBytes, _ := json.Marshal(dim)
// ? {"width":100,"height":200,"depth":50,"unit":"cm"}
CurrencyField
price := types.CurrencyField{
Amount: 99.99,
Currency: "USD",
}
jsonBytes, _ := json.Marshal(price)
// ? {"amount":99.99,"currency":"USD"}
PasswordField
type User struct {
Email types.EmailField `json:"email"`
Password types.PasswordField `json:"password"`
}
// Create new password
pwd, err := types.NewPassword("MyS3cretPass!")
if err != nil {
panic(err)
}
user := User{Email: "user@example.com", Password: pwd}
// Marshal to JSON
jsonBytes, _ := json.Marshal(user)
// Output: { "email":"user@example.com", "password":"********" }
// Compare passwords
isValid := user.Password.ComparePassword("MyS3cretPass!")
fmt.Println(isValid) // true
Decimal
// Create decimals
d1, _ := types.NewFromString("10.50")
d2 := types.NewFromInt(2)
d3 := types.NewFromFloat(3.14159)
// Arithmetic
sum := d1.Add(d2) // 12.50
diff := d1.Sub(d2) // 8.50
prod := d1.Mul(d3) // 32.986...
quot, _ := d1.Div(d2) // 5.25
// Comparison
fmt.Println(d1.GreaterThan(d2)) // true
fmt.Println(d1.Equal(d2)) // false
// Rounding
rounded := d3.Round(2) // 3.14
// Square root
sqrt, _ := d1.Sqrt() // ~3.240370349
// Conversion
fmt.Println(d1.String()) // "10.5"
f64, _ := d1.Float64() // 10.5
i64 := d1.Int64() // 10
// JSON
jsonBytes, _ := json.Marshal(d1)
// ? "10.5"
// Database (GORM model)
type Invoice struct {
ID uint
Amount types.Decimal `json:"amount"`
}
Environment Variables
-
APP_URL? Used by FileField to build absolute file URLs.- Example:
APP_URL=https://example.com
- Example:
Database Integration
All custom types implement:
driver.Valuer? For writing to the database.sql.Scanner? For reading from the database.
That means you can use them directly in GORM models.
type Product struct {
ID uint
Name string
Price types.CurrencyField
Size types.DimensionField
Location types.GeoLocationField
}
License
This package is licensed under the GNU Lesser General Public License (LGPL) v3.