Skip to content

Go SDK

The official Go SDK for JSONQL. A few lines of configuration give your API dynamic filtering, sorting, pagination, field selection, and relationships — no custom handlers needed.

Modulegithub.com/jsonql-standard/jsonql-go
Go version1.24+
LicenseMIT
SpecJSONQL v1.1
Terminal window
go get github.com/jsonql-standard/jsonql-go

Pick your framework — a few lines give you a complete JSONQL API:

package main
import (
"github.com/gin-gonic/gin"
"github.com/jsonql-standard/jsonql-go/adapters/gin"
"github.com/jsonql-standard/jsonql-go/adapters/http"
"github.com/jsonql-standard/jsonql-go/drivers/postgres"
)
func main() {
driver, _ := postgres.NewDriver("postgres://localhost/mydb?sslmode=disable")
defer driver.Close()
handler, _ := gin.Handler(http.AdapterOptions{Driver: driver})
r := gin.Default()
r.NoRoute(handler) // All routes handled automatically
r.Run(":8080")
}
package main
import (
"github.com/labstack/echo/v4"
jsonqlecho "github.com/jsonql-standard/jsonql-go/adapters/echo"
"github.com/jsonql-standard/jsonql-go/adapters/http"
"github.com/jsonql-standard/jsonql-go/drivers/postgres"
)
func main() {
driver, _ := postgres.NewDriver("postgres://localhost/mydb?sslmode=disable")
defer driver.Close()
handler, _ := jsonqlecho.Handler(http.AdapterOptions{Driver: driver})
e := echo.New()
e.Any("/*", handler) // Catch-all — table name from URL path
e.Start(":8080")
}
package main
import (
"net/http"
jsonqlhttp "github.com/jsonql-standard/jsonql-go/adapters/http"
"github.com/jsonql-standard/jsonql-go/drivers/sqlite"
)
func main() {
driver, _ := sqlite.NewDriver("./my.db")
defer driver.Close()
handler, _ := jsonqlhttp.Handler(jsonqlhttp.AdapterOptions{Driver: driver})
http.Handle("/", handler)
http.ListenAndServe(":8080", nil)
}

That’s it. One driver, one handler mount. Your clients can now query any table dynamically.

Every query is a JSON POST to /{table}:

Terminal window
# Select specific fields, filter, sort, paginate
curl -X POST http://localhost:8080/users -H 'Content-Type: application/json' -d '{
"fields": ["id", "name", "email"],
"where": { "status": { "eq": "active" } },
"sort": ["-created_at"],
"limit": 20
}'
# → { "data": [{ "id": 1, "name": "Alice", "email": "alice@co.com" }, ...] }
Terminal window
# Complex filters
curl -X POST http://localhost:8080/products -d '{
"where": {
"and": [
{ "price": { "gte": 10, "lte": 100 } },
{ "category": { "in": ["electronics", "books"] } }
]
},
"sort": ["price"],
"limit": 50
}'
Terminal window
# Include related data — joins resolved automatically
curl -X POST http://localhost:8080/users -d '{
"fields": ["id", "name"],
"include": {
"posts": { "fields": ["title", "created_at"], "limit": 5 }
}
}'
Terminal window
# Aggregation & groupBy
curl -X POST http://localhost:8080/orders -d '{
"aggregate": { "total": { "fn": "sum", "field": "amount" } },
"groupBy": ["status"]
}'

CRUD mutations:

Terminal window
# Create
curl -X POST http://localhost:8080/users \
-d '{ "data": { "name": "Bob", "email": "bob@co.com" } }'
# Update
curl -X PATCH http://localhost:8080/users \
-d '{ "patch": { "status": "inactive" }, "where": { "id": { "eq": 1 } } }'
# Delete
curl -X DELETE http://localhost:8080/users \
-d '{ "where": { "id": { "eq": 1 } } }'

Without schema, all columns are queryable. With schema, you control which fields are exposed, enable relationship resolution, and restrict access:

handler, _ := gin.Handler(http.AdapterOptions{
Driver: driver,
Schema: &jsonql.JSONQLSchema{
Tables: map[string]*jsonql.JSONQLTable{
"users": {
Fields: map[string]*jsonql.JSONQLField{
"id": {Type: "number"},
"name": {Type: "string"},
"email": {Type: "string"},
},
Relations: map[string]*jsonql.JSONQLRelation{
"posts": {Type: "hasMany", Table: "posts", Field: "user_id"},
},
},
},
},
})

Inject tenant isolation, audit logging, or custom logic:

handler, _ := gin.Handler(http.AdapterOptions{
Driver: driver,
Hooks: &jsonql.Hooks{
BeforeQuery: func(query map[string]any, table string) {
// Add tenant filter to every query
query["where"] = map[string]any{
"and": []any{query["where"], map[string]any{"tenant_id": map[string]any{"eq": tenantID}}},
}
},
},
})
DatabaseImport PathUnderlying Driver
PostgreSQLdrivers/postgresgithub.com/lib/pq
MySQLdrivers/mysqlgithub.com/go-sql-driver/mysql
SQLitedrivers/sqlitemodernc.org/sqlite
MSSQLdrivers/mssqlgithub.com/microsoft/go-mssqldb
MongoDBdrivers/mongodbgo.mongodb.org/mongo-driver

All errors implement JsonQLError with a Code() string method:

graph TD
E["JsonQLError interface"] --> P["JsonQLParseError<br/>(PARSE_ERROR)"]
E --> V["JsonQLValidationError<br/>(VALIDATION_ERROR)"]
E --> T["JsonQLTranspileError<br/>(TRANSPILE_ERROR)"]
E --> X["JsonQLExecutionError<br/>(EXECUTION_ERROR)"]
var jsonqlErr jsonql.JsonQLError
if errors.As(err, &jsonqlErr) {
fmt.Println(jsonqlErr.Code()) // "VALIDATION_ERROR"
}

Adapter error responses:

{ "error": "Field 'secret' is not allowed", "error_code": "VALIDATION_ERROR" }

For custom pipelines outside the adapters:

engine := jsonql.NewEngineBuilder().
Postgres().
Schema(schema).
Executor(func(ctx context.Context, sql string, args []interface{}) (*sql.Rows, error) {
return db.QueryContext(ctx, sql, args...)
}).
Build()
result, err := engine.Execute(ctx, "users", queryMap)
// result.Data — []map[string]interface{}
// result.IsMutation — bool

For server-side programmatic query construction:

import "github.com/jsonql-standard/jsonql-go/builder"
q := builder.New().
From("users").
Select("id", "name", "email").
Where(map[string]any{"status": map[string]any{"eq": "active"}}).
OrderBy("-created_at").
Limit(10).
Build()
TypePurpose
AdapterOptionsConfigure adapter: driver, schema, hooks
Driver interfaceDatabase abstraction: Query(), Execute(), Close()
Engine / EngineBuilderProgrammatic transpile-and-execute pipeline
ParserParse & validate incoming JSON
TranspilerConvert parsed query → SQL + args
HydratorConvert flat rows → nested JSON
QueryBuilderFluent query construction (advanced)

135/135 tests passing across all configurations:

AdapterPostgreSQLMySQLSQLiteMSSQLMongoDB
Gin
Echo
net/http
Terminal window
make test # Run all tests
go vet ./... # Static analysis (CI enforced)
gofmt -w . # Auto-format

github.com/jsonql-standard/jsonql-go