jsonflag

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 7, 2025 License: Apache-2.0 Imports: 7 Imported by: 0

README

jsonflag

jsonflag is a tiny Go library that can turn any JSON-marshallable struct into a set of command‑line flags. It works with the standard flag package and with the popular pflag package, handling nested structs, slices, maps and pointer fields automatically.

Go Reference Go Report Card

Adding to project

First, use go get to download and add the latest version of the library to the project.

go get -u github.com/daishe/jsonflag

Then include in your source code.

import "github.com/daishe/jsonflag"

Usage example (with standard go flag package)

package main

import (
	"flag"
	"fmt"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"

	"github.com/daishe/jsonflag"
)

func main() {
	config := struct {
		URL struct {
			Scheme string `json:"scheme"`
			Host   string `json:"host"`
			Port   int    `json:"port"`
			Path   string `json:"path"`
		} `json:"url"`
		Verbose bool `json:"verbose"`
	}{}

	// default values
	config.URL.Scheme = "https"
	config.URL.Host = "localhost"
	config.URL.Port = 8080

	fs := flag.NewFlagSet("", flag.ExitOnError) // you can also add it directly to the root flag set
	for _, val := range jsonflag.Recursive(&config) {
		fs.Var(val, jsonflag.JSONName(val.Path()), jsonflag.Usage(val.Path()))
	}
	if err := fs.Parse(os.Args[1:]); err != nil {
		fmt.Fprintf(os.Stderr, "Arguments parsing error: %v\n", err)
		os.Exit(1)
	}

	u := url.URL{
		Scheme: config.URL.Scheme,
		Host:   fmt.Sprintf("%s:%d", config.URL.Host, config.URL.Port),
		Path:   config.URL.Path,
	}

	resp, err := http.Get(u.String())
	if err != nil {
		fmt.Fprintf(os.Stderr, "Doing request error: %v\n", err)
		os.Exit(1)
	}
	defer resp.Body.Close()

	if config.Verbose {
		respBytes, err := httputil.DumpResponse(resp, true)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Dumping response error: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("%s\n", respBytes)
	}
}

License

The project is released under the Apache License, Version 2.0. See the full LICENSE file for the complete terms and conditions.

Documentation

Overview

Package jsonflag is a tiny Go library that can turn any JSON-marshallable struct into a set of command‑line flags.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func DashCase

func DashCase(s string) string

DashCase converts Go camel case flag name into dash case flag name, eg. "Foo.FooBar.FooBarBaz" to "foo.foo-bar.foo-bar-baz".

func JSONName

func JSONName(path []reflect.StructField) string

JSONName creates a new flag name by joining all JSON names (as package "encoding/json" would generate them) of struct fields along the provided path.

func JsonCamelCase

func JsonCamelCase(s string) string

JsonCamelCase converts Go camel case flag name into JSON (javascript) camel case flag name, eg. "Foo.FooBar.FooBarBaz" to "foo.fooBar.fooBarBaz".

func Name

func Name(path []reflect.StructField) string

Name creates a new flag name by joining all names of struct fields along the provided path.

func SnakeCase

func SnakeCase(s string) string

SnakeCase converts Go camel case flag name into snake case flag name, eg. "Foo.FooBar.FooBarBaz" to "foo.foo_bar.foo_bar_baz".

func Usage

func Usage(path []reflect.StructField) string

Usage attempts to retrieve from the last element of path a tag value under key 'usage', 'description' or 'desc'.

Types

type FilterFunc

type FilterFunc func(*Value) FilterResult

FilterFunc is a function that can be used to decide if a flag value should be included in recursive results as well as if flag values finding should descend into the sub-values.

type FilterResult

type FilterResult uint32

FilterResult is a bit field holding filtering decision.

const (
	IncludeAndDescend FilterResult = 0b00 // indicates that the given flag value should be included and values finding should descend into sub-values
	IncludeNoDescend  FilterResult = 0b01 // indicates that the given flag value should be included, but values finding should NOT descend into sub-values
	SkipAndDescend    FilterResult = 0b10 // indicates that the given flag value should be skipped, but values finding should descend into sub-values
	SkipNoDescend     FilterResult = 0b11 // indicates that the given flag value should be skipped and values finding should NOT descend into sub-values

)

func Filter

func Filter(val *Value, filters ...FilterFunc) (r FilterResult)

Filter applies all filter function to the provided flag value and returns filtering decision.

type Value

type Value struct {
	// contains filtered or unexported fields
}

func New

func New(base any) *Value

New returns new flag value for the provided value. It returns nil if the value cannot be used as flag value.

func Recursive

func Recursive(base any, filters ...FilterFunc) []*Value

Recursive returns set of flag values for the provided value and all values within, recursively, according to the provided filters. Function silently skips all the values that cannot be used as flag values.

Example (WithGoFlag)
package main

import (
	"encoding/json"
	"flag"
	"fmt"

	"github.com/daishe/jsonflag"
)

func main() {
	type Input struct {
		Foo string `json:"Foo"`
		Bar string `json:"Bar"`
		Baz string `json:"Baz"`
	}

	fs := flag.NewFlagSet("", flag.ExitOnError)
	i := &Input{}
	for _, val := range jsonflag.Recursive(i) {
		fs.Var(val, jsonflag.Name(val.Path()), jsonflag.Usage(val.Path()))
	}
	if err := fs.Parse([]string{"--Foo=foo value", "--Baz=baz value"}); err != nil {
		panic(err)
	}

	b, err := json.MarshalIndent(i, "", "  ")
	if err != nil {
		panic(err)
	}
	fmt.Println(string(b))

}
Output:

{
  "Foo": "foo value",
  "Bar": "",
  "Baz": "baz value"
}
Example (WithPFlag)
package main

import (
	"encoding/json"
	"fmt"

	"github.com/daishe/jsonflag"
	"github.com/spf13/pflag"
)

func main() {
	type Input struct {
		Foo string `json:"Foo"`
		Bar string `json:"Bar"`
		Baz string `json:"Baz"`
	}

	fs := pflag.NewFlagSet("", pflag.ExitOnError)
	i := &Input{}
	for _, val := range jsonflag.Recursive(i) {
		pf := &pflag.Flag{
			Name:     jsonflag.Name(val.Path()),
			Usage:    jsonflag.Usage(val.Path()),
			Value:    val,
			DefValue: val.String(),
		}
		if val.IsBoolFlag() {
			pf.NoOptDefVal = "true"
		}
		fs.AddFlag(pf)
	}
	if err := fs.Parse([]string{"--Foo=foo value", "--Baz=baz value", "--Baz=another baz value"}); err != nil {
		panic(err)
	}

	b, err := json.MarshalIndent(i, "", "  ")
	if err != nil {
		panic(err)
	}
	fmt.Println(string(b))

}
Output:

{
  "Foo": "foo value",
  "Bar": "",
  "Baz": "another baz value"
}

func (*Value) Get

func (val *Value) Get() any

func (*Value) IsBoolFlag

func (val *Value) IsBoolFlag() bool

func (*Value) Path

func (val *Value) Path() []reflect.StructField

func (*Value) Set

func (val *Value) Set(to string) error

func (*Value) SetDecoder

func (val *Value) SetDecoder(fn func([]byte, any) error)

func (*Value) SetEncoder

func (val *Value) SetEncoder(fn func(any) ([]byte, error))

func (*Value) String

func (val *Value) String() string

func (*Value) Type

func (val *Value) Type() string

Directories

Path Synopsis
examples
simplecurl command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL