+
Skip to content

teacat/qparser

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

qparser GoDoc Coverage Status Build Status Go Report Card

The library parses search query (e.g. title:"hello world" limit:42) to struct with plain text fallback 😎.

package main

import (
	"time"

	"github.com/teacat/qparser"
)

type SearchFilter struct {
	Keyword string    `query:"keyword,default"` // Falls back for plain text
	Title   string    `query:"title"`
	Limit   int       `query:"limit"`
	Tags    []string  `query:"tags"`
	Before  time.Time `query:"before,format=2006-01-02"`
}

func main() {
	q := `hello world title:foobar limit:42 tags:admin,editor,guest before:2024-12-31`

	var filter SearchFilter
	if err := qparser.Unmarshal(q, &filter); err != nil {
		panic(err)
	}

	// Keyword: hello world
	// Title  : foobar
	// Limit  : 42
	// Tags   : [admin editor guest]
	// Before : 2024-12-31 00:00:00 +0000 UTC
}

Installation

$ go get -u github.com/teacat/qparser

Table of Contents

Functions

Function Description
IsQuery(input string) bool Check if input string contains search query syntax
Unmarshal(input string, target any) error Parse input into target struct
UnmarshalStrict(input string, target any) error Same as above but returns error if invalid type or unknown field

Field Types

The parser supports the following Go types.

  • Pointer types remain nil when not specified in the query
  • Non-pointer types are set to zero value when not specified in the query
Basic Types Pointer Types Slice Types
string *string []string
bool *bool -
int *int []int
int8 *int8 []int8
int16 *int16 []int16
int32 *int32 []int32
int64 *int64 []int64
uint *uint []uint
uint8 *uint8 []uint8
uint16 *uint16 []uint16
uint32 *uint32 []uint32
uint64 *uint64 []uint64
float32 *float32 []float32
float64 *float64 []float64
time.Time *time.Time -

Struct Tags

Use the query tag to configure field behavior:

Tag Description
query:"fieldname" Maps search query to struct field
query:"fieldname,default" Marks field as default for plain text queries
query:"fieldname,format=2006-01-02" Custom time format for time.Time fields

Examples

Basic Parsing

Search queries use the format field:value or field:"quoted value" for values with spaces.

type Filter struct {
    Title    string `query:"title"`
    Author   string `query:"author"`
    Category string `query:"category"`
}

q := `title:hello author:world category:"science fiction"`

// Title   : hello
// Author  : world
// Category: science fiction

Fallback Parsing

When input doesn't contain search query syntax, it falls back to the field marked with default.

type Filter struct {
    Query string `query:"query,default"`
    Type  string `query:"type"`
}

q := `search for golang tutorials`

// Query: search for golang tutorials
// Type :

Enhanced Fallback Parsing

Query fields take precedence, and remaining text or unknown field goes to default field.

type Filter struct {
    Keyword  string `query:"keyword,default"`
    Category string `query:"category"`
}

q := `hello world category:books foo bar emotion:happy`

// Keyword : hello world foo bar emotion:happy
// Category: books

Numeric Parsing

The parser supports all Go numeric types.

type Filter struct {
    Price    float64 `query:"price"`
    Discount float32 `query:"discount"`
    Quantity uint32  `query:"qty"`
    MinAge   int8    `query:"min_age"`
    MaxSize  uint64  `query:"max_size"`
}

q := `price:10.10 discount:0.10 qty:100 min_age:10 max_size:100000`

// Price   : 10.10
// Discount: 0.10
// Quantity: 100
// MinAge  : 10
// MaxSize : 100000

Slice Parsing

The parser supports slices of all numeric types and strings with comma-separated (no space between) values.

type Filter struct {
    Tags    []string  `query:"tags"`
    Scores  []int     `query:"scores"`
    Weights []float64 `query:"weights"`
}

q := `tags:foo,bar scores:10,20,30 weights:0.1,0.2,0.3`

// Tags   : { "foo", "bar" }
// Scores : { 10, 20, 30 }
// Weights: { 0.1, 0.2, 0.3 }

Note: For values containing spaces or commas, wrap the value in quotes:

q := `tags:"hello world,golang,web dev"`
// Tags: { "hello world", "golang", "web dev" }

Time Parsing

The parser supports custom/multiple formats for a single field. The parser will try each format until one succeeds.

Default formats are used when no custom format is specified.

type Filter struct {
    StartedAt   time.Time `query:"started_at"`                                  // Default formats are 2006, 2006-01, 2006-01-02
    EndedAt     time.Time `query:"ended_at,format=01/02/2006"`                  // Custom US format
    PublishDate time.Time `query:"publish_date,format=2006 2006-01 2006-01-02"` // Multiple formats (space-separated)
}

q := `started_at:2025-12-30 ended_at:30/12/2025 publish_date:2025`

// StartedAt  : time.Date(2025, 12, 30, 0, 0, 0, 0, time.UTC)
// EndedAt    : time.Date(2025, 12, 30, 0, 0, 0, 0, time.UTC)
// PublishDate: time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC)

Boolean Parsing

The parser supports both regular bool and optional *bool (pointer) types.

type Filter struct {
    IsActive   bool  `query:"is_active"`
    IsRequired *bool `query:"is_required"` // nil if not specified
}

q := `is_active:true`

// IsActive  : true
// IsRequired: nil

The parser accepts the following values for boolean fields (case-insensitive):

Parsed As Value Examples
true true, 1, yes, y, on active:true, enabled:1
false false, 0, no, n, off active:false, hidden:0

Note: Any unrecognized boolean value will result in false and may trigger an error in strict mode.

About

🔍 Converts search query DSL to Golang Struct

Resources

Stars

Watchers

Forks

Languages

点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载