There is an ongoing outage on the primary CPAN mirror. It is possible to work around the issue by using MetaCPAN as a mirror.

NAME

MOP4Import::Base::CLI_JSON - Base class for rapidly building testable CLI modules with JSON I/O

SYNOPSIS

#!/usr/bin/env perl
package MyScript;

use MOP4Import::Base::CLI_JSON -as_base,
    [fields =>
      [verbose => doc => "Enable verbose output", json_type => 'bool'],
      [config  => doc => "Config file path", json_type => 'string']
    ];

MY->cli_run(\@ARGV) unless caller;

# Official CLI command - handles its own output
sub cmd_status : Doc("Show system status") {
  my ($self) = @_;
  print "System OK\n";
}

# Regular method - output handled by CLI_JSON
sub query {
  my ($self, $sql) = @_;
  # Returns data structure that will be JSON-encoded
  return {result => "data from $sql"};
}

1;

From shell:

# Show help
$ ./MyScript.pm --help

# Call official command
$ ./MyScript.pm status
System OK

# Call regular method (output as NDJSON by default)
$ ./MyScript.pm query "SELECT * FROM users"
{"result":"data from SELECT * FROM users"}

# Use different output format
$ ./MyScript.pm --output=yaml query "test"
---
result: data from test

# Pass complex data structures as arguments
$ ./MyScript.pm process '{"key":"value"}' '[1,2,3]'

DESCRIPTION

MOP4Import::Base::CLI_JSON enables rapid development of Perl modules by making any method immediately testable from the command line. It provides automatic JSON serialization for inputs and outputs, making it ideal for exploratory development and debugging.

Key features:

  • Instant CLI access to any module method

  • Automatic JSON encoding/decoding of arguments and return values

  • Multiple output formats (ndjson, json, yaml, tsv, dump, raw)

  • Direct integration with debugger (perl -d) and profiler

  • Type checking via json_type field declarations

For conceptual background, see OO Modulino Pattern.

USAGE

Creating a CLI_JSON Module

To create a module that can be used both as a library and CLI tool:

package MyModule;
use MOP4Import::Base::CLI_JSON -as_base;

MY->cli_run(\@ARGV) unless caller;

# Your methods here
1;

The unless caller idiom ensures cli_run only executes when the file is run directly, not when it's loaded as a module.

Command Resolution Rules

When invoked from CLI, the first argument is treated as the command name:

cmd_$COMMAND

If a method cmd_$COMMAND exists, it's treated as an official CLI command. The method is responsible for all output and exit handling.

$COMMAND

If a method matching the command name exists, it's invoked and its return value is automatically serialized according to the --output option.

Unknown commands

If no matching method exists, cli_unknown_subcommand is called, which by default shows an error message and help.

Field Declarations

Fields can be declared with type information and documentation:

use MOP4Import::Base::CLI_JSON -as_base,
  [fields =>
    [dbfile =>
      doc => "Database file path",
      default => ":memory:",
      json_type => 'string'
    ],
    [limit =>
      doc => "Result limit",
      json_type => 'integer',
      validator => sub { $_[0] > 0 }
    ]
  ];

Field Options

doc

Documentation string shown in help output

default

Default value for the field

json_type

JSON Schema type for validation. Supported types: string, bool, boolean, int, integer, number

validator

Code reference for custom validation. Receives the value and should return true if valid.

CORE METHODS

cli_run(\@ARGV, \%shortcuts)

MY->cli_run(\@ARGV) unless caller;

# With option shortcuts
MY->cli_run(\@ARGV, {h => 'help', v => 'verbose'}) unless caller;

Main entry point for CLI execution. Parses arguments, creates an instance, and invokes the appropriate method. Options before the command become constructor arguments, remaining arguments are passed to the method.

Option format: --name or --name=value (no space between name and value).

JSON values in options and arguments are automatically decoded:

$ ./MyScript.pm --config='{"port":8080}' process '[1,2,3]'

Command Methods

Official Commands (cmd_*)

Methods prefixed with cmd_ are official CLI commands:

sub cmd_import : Doc("Import data from file") {
  my ($self, $file) = @_;
  # Handle own output
  print "Importing $file...\n";
  # Handle own exit code if needed
  exit($success ? 0 : 1);
}

Regular Methods

Regular methods have their return values automatically serialized:

sub calculate {
  my ($self, $x, $y) = @_;
  return {result => $x + $y};  # Will be JSON-encoded
}

Output Control Methods

cli_output(\@results)

Called automatically to output method results. Can be overridden for custom output handling.

cli_write_fh($filehandle, @data)

Low-level output method that respects the --output format option.

OPTIONS

These options control CLI behavior and are processed by cli_run:

--help

Show help message and exit

--quiet

Suppress normal output

--scalar

Evaluate methods in scalar context (default is list context)

--output=FORMAT

Output format: ndjson (default), json, yaml, tsv, dump, raw

--flatten

Flatten array results (useful with --output=tsv)

--undef-as=STRING

How to represent undef in TSV output (default: "null")

--no-exit-code

Don't set exit code based on results

--binary

Keep STDIN/STDOUT/STDERR in binary mode (no UTF-8 encoding)

OUTPUT FORMATS

ndjson (default)

Newline Delimited JSON - one JSON object per line. Ideal for:

  • Large result sets (human readable without pretty-printing)

  • Pipeline processing with grep, awk, etc.

  • Streaming output

json

Standard JSON format with pretty-printing

yaml

YAML format (requires YAML::Syck)

tsv

Tab-separated values, useful for spreadsheet import

dump

Perl Data::Dumper output for debugging

raw

No serialization, raw string output

UTILITY METHODS

These methods are available for use in your modules:

cli_decode_json($json_string)

Decode a JSON string to Perl data structure

cli_encode_json($data)

Encode Perl data structure to JSON string

cli_read_file($filename)

Read and parse a file based on its extension (.json, .yml, .txt)

DEVELOPMENT WORKFLOW

CLI_JSON is designed to accelerate development through immediate feedback:

# 1. Create minimal module
package MyModule;
use MOP4Import::Base::CLI_JSON -as_base;
MY->cli_run(\@ARGV) unless caller;
1;
# 2. Check syntax
$ perl -wc MyModule.pm

# 3. Add a method and test immediately
$ ./MyModule.pm my_method "arg1" "arg2"

# 4. Debug interactively
$ perl -d ./MyModule.pm my_method "test"

# 5. Profile performance
$ perl -d:NYTProf ./MyModule.pm heavy_method

SEE ALSO

LICENSE

Copyright (C) Kobayasi, Hiroaki.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

AUTHOR

Kobayasi, Hiroaki <buribullet@gmail.com>