How to Reuse jq Filters with import, include, and -f
To reuse a jq filter, choose between an inline def (one program), a saved program with -f (run the same program again), or a module with import or include (share functions between different programs). The examples first show jq CLI syntax, then show how a Java application can reuse the same files. The browser playground accepts inline definitions but does not load module files.
For the examples below, save this input as input.json:
{"name":"Ada"}
Each command outputs "ADA".
Define a helper in one filter
jq 'def display_name: .name | ascii_upcase; display_name' input.json
def gives part of a filter a name. The definition is available inside this jq program, but a separate jq command will not inherit it. In the browser jq playground, put both the def and the expression that calls it in the filter editor.
Save and rerun a whole program with -f
Save filter.jq:
def display_name: .name | ascii_upcase;
display_name
Then run it against any compatible JSON input:
jq -f filter.jq input.json
-f reads the entire jq program from filter.jq instead of a quoted command-line filter. It does not automatically make its definitions available to other jq files. A runnable program needs a final expression after its def statements; filter.jq ends with display_name.
Share functions between jq programs with import
Save only the reusable definition in helpers.jq:
def display_name: .name | ascii_upcase;
Import it into a command-line filter under a namespace:
jq -L . 'import "helpers" as h; h::display_name' input.json
-L . tells jq to look for modules in the current directory. The import name omits .jq; import "helpers" as h loads helpers.jq, and h::display_name calls its function. A second program can reuse the same module without copying the definition:
import "helpers" as h;
{label: h::display_name}
Save this program as label.jq, then run jq -L . -f label.jq input.json to get {"label":"ADA"}. Use a project directory in place of . when modules are stored elsewhere. A missing module or function is a jq error, not a fallback to an empty result.
Use include for an unqualified function name
If you do not need a namespace, the same helpers.jq also works with:
jq -L . 'include "helpers"; display_name' input.json
include makes display_name available without the h:: prefix. Prefer import ... as h when multiple modules might define the same name; include is convenient for a small shared helper library.
Reuse the same files from Java or another application
If your application invokes the jq executable, pass arguments directly rather than building a shell command string. For example, with helpers.jq, label.jq, and input.json from above in the Java process's working directory:
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class RunJq {
public static void main(String[] args) throws IOException, InterruptedException {
Process process = new ProcessBuilder(
"jq", "-L", ".", "-f", "label.jq", "input.json"
).redirectErrorStream(true).start();
String output = new String(process.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
int exitCode = process.waitFor();
if (exitCode != 0) {
throw new IllegalStateException("jq exited " + exitCode + ": " + output);
}
System.out.print(output);
}
}
This prints {"label":"ADA"} (jq may add spaces in its JSON output). The application needs jq installed on its PATH; -L still controls module lookup, and -f still loads the main program. ProcessBuilder does not invoke a shell here, so no shell quoting or interpolation is needed.
If instead you use an in-process jq library that accepts filter source text, the portable option is to read a shared definition and append a final expression before giving the resulting source to that library:
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
String source = Files.readString(Path.of("helpers.jq"), StandardCharsets.UTF_8)
+ "\ndisplay_name";
// Pass source and your JSON input to your jq library's compile/evaluate API.
This produces the same jq program as the inline def example, without depending on the library's module loader. The last line is an integration step, not a universal Java jq API: libraries differ in how they compile filters and supply input. If your library supports module resolution, configure its module search path and use import/include instead; CLI switches like -L and -f are not automatically available inside an embedded library. Do not concatenate untrusted input into jq source; pass values through your library's argument/input API.
The CLI examples above were verified with jq 1.8.1. -f loads a program and -L selects where import/include find modules; they solve different reuse needs and can be combined. If you want to pass data rather than code, use --arg or --argjson to pass shell values instead. The jq cheatsheet covers more filter syntax. Reference: jq manual, invoking jq and jq modules.