How to print JSON output from your CLI

C01t has been hard at work building the command line app for project Feijoa. He has taken great care to include all the tips from Naomi and Sam into the app. First of all, C01t chose Go as the programming language. He is planning to release the CLI app for all 3 major desktop operating system: Windows, Linux and OS X. In addition, he picked the spf13/cobra library to speed up development. C01t also decided to support human readable and JSON output from the start for every command.

Finally, C01t has been writing docs and READMEs to capture his coding choices along the way. So today he is documenting the command output pattern.

Command output

Most command line apps focus on producing human readable output. But having machine readable output, such as JSON output, is just as important. Machine readable output unlocks additional use cases, eg. scripting of the CLI, and improves testability. Furthermore, we aim to build helpers for rendering machine readable output from every command.

Output mode flag

To control how the CLI renders output, we define an “output mode” flag. Furthermore, we aim to implement the flag consistently across all commands.


const (
	// OutputModeFlag is the name for the flag that lets user specify the
	// desired output mode.
	OutputModeFlag = "output"

	// OutputModeFlagShorthand is the shorthand value for the OutputModeFlag.
	OutputModeFlagShorthand = "o"
)

In addition, we define the set of values for the flag. We start with human readable output, “standard”, and JSON output. In the future, we can extend the values list easily to support new output modes.


// Valid values for OutputModeFlag.
const (
	OutputModeStandard = "standard"
	OutputModeJSON = "json"
)

Finally, we add the output mode flag as a persistent flag to the root command. As a result, the flag can be set on every command.


rootCmd.PersistentFlags().StringP(
	OutputModeFlag,
	OutputModeFlagShorthand,
	OutputModeStandard,
	fmt.Sprintf(
		"Command output mode. One of: %s, %s", OutputModeStandard, OutputModeJSON),
)

The action function

First of all, each command must collect the data to be rendered in machine readable format. So action functions return both a result struct and error. The signature of an action function could look something like:


func MyAction(cmd *cobra.Command, args []string) (ActionResult, error)

The result struct serves as the collector of data produced as the action is executed. In addition, we use struct tags control the serialization of the results.


type ActionResult struct {
	Message string `json:"msg,omitempty"`
}

Finally, we can emit human readable output inside the action function body. The only limitation is that we must write all output to the writer attached to the cmd param:


fmt.Fprint(cmd.OutOrStdout(), "Hello world")

Since, the app displays information as a command is running, it fells more responsive and interactive. However, we can suppress this output by setting the writer on the cmd param to ioutil.Discard. Doing so keeps human readable output from interfering with the machine readable output.

The helpers

So far we have we have seen the base building blocks for implementing JSON output. Therefore it is now time to see how we tie it all together.

First we create a functions to map the action function we defined previously to the action function signatures expected for the spf13/cobra framework. The code sample below implements a function to map to the RunE action function:


type (
	// RunEAction defines the function signature for the action to be wrapped by
	// RunE.
	RunEAction func(cmd *cobra.Command, args []string) (interface{}, error)
)

func RunE(
	action RunEAction,
) (func(cmd *cobra.Command, args []string) error) {
	return func(cmd *cobra.Command, args []string) error {
		return runE(action, cmd, args)
	}
}

Most noteworthy in the code above is the runE function. The function determines the active output mode. Then it invokes helpers to execute the action and produce the output.


func runE(action RunEAction, cmd *cobra.Command, args []string) error {
	mode, err := cmd.Flags().GetString(OutputModeFlag)
	if err != nil {
		return errors.Wrap(err, "failed to determine output mode")
	}

	switch mode {
	case OutputModeStandard:
		err = runEStandard(action, cmd, args)
	case OutputModeJSON:
		err = runEJSON(action, cmd, args)
	default:
		err = errors.Errorf("unsupported output mode: '%s'", mode)
	}
	return err
}

runEStandard just calls the action function. runEJSON sets the output writer on cmd to ioutil.Discard. Then executes the action function. And renders the result as JSON.

Finally, we declare a command as follows:


cmd := &cobra.Command{
	Use: "my-cmd",
	RunE: RunE(MyAction),
}

Coda

The Green GUAVA cookiecutter-go template has a full implementation of the helpers described. Use the template to build CLI apps with a variety of output modes.


Image by: unsplash-logoJustin Peralta

2,920 Replies to “How to print JSON output from your CLI”

  1. У софта Leon имеется ряд существенных плюсов: более быстрая скорость работы (т.к. программа располагается на самом гаджете), тратит меньшее количество “метров”, а также ничем не отличается по возможностям от моби-версии.
    На сайте Леона можно ознакомиться с приложениями для Android и АйОС.
    Программы Leon доступны для большинства актуальных версий АйОС и Android .
    Программы букмекера Leonbets почти ничем не отличаются от основной версии сайта , кроме того, что в программе Леона нет раздела “Топ лиги”.
    Желательно скачивать приложения Leonbets по ссылкам с официального сайта, так как приложения со сторонних ресурсов могут нести в себе мошенническое ПО и нанести вред вашему гаджету.
    ПО Leon для Андроид.
    ПО Leonbets для Андроид нельзя скачать в Плей Маркете из-за политики Google в части азартных игр.
    По клику “Скачать” на ваш телефон начинает скачиваться apk, который может потребовать разрешения на установку.
    При установке софта Леон новым клиентам предусмотрен бесплатная ставка на 500 р..
    Сразу после инсталла переходим в программу и сразу можем сравнить его с мобильной версией сайта и leon.ru:
    Cущественных различий не наблюдается: приложение создано в черных цветахБК Leon, имеет такие же разделы, что мы видим на сайте.
    После выбора исхода можно перейти во вкладку купона, чтобы сделать ставку.
    Через программу Леон можно также пройти регистрацию.
    В live можносмотреть анимированную трансляцию.
    В меню приложения можно выбрать цветовую оболочку оформления: “темную” или “светло-серую”.
    Преимуществами ПО для Андроида стала корректная работа, похожее расположение всех элементов сайтаLeon, а также быстрое обслуживание в live и стартовый бонус.
    Недостатком же является отсутствие статистики матчей.
    ПО компании Леонбетс на АйОС.
    Программу Leonbets можно скачать через официальный магазин Эпл.
    Приложения на iOS и Android от БК Леонбетс по сути совпадают. возможен вход в приложение по отпечатку пальца через TouchID.
    Приложение букмекерской конторы Леонбетс на ПК.
    У компании Leon отсутствует приложение для персонального компьютера.
    https://anotepad.com/notes/ctx8trc7

Comments are closed.