JSON Mode
Composability is a key perk of command line tooling. ast-grep is no exception.
--json
will output results in JSON format. This is useful to pipe the results to other tools.
Example:
sg run -p 'Some($A)' -r 'None' --json
Output Data Structure
The format of the JSON output is an array of match objects. Below is an example of a match object generated from the command above.
[
{
"text": "Some(matched)",
"range": {
"byteOffset": { "start": 10828, "end": 10841 },
"start": { "line": 303, "column": 2 },
"end": { "line": 303, "column": 15 }
},
"file": "crates/config/src/rule/mod.rs",
"lines": " Some(matched)",
"replacement": "None",
"replacementOffsets": { "start": 10828, "end": 10841 },
"language": "Rust",
"metaVariables": {
"single": {
"A": {
"text": "matched",
"range": {
"byteOffset": { "start": 10833, "end": 10840 },
"start": { "line": 303, "column": 7 },
"end": { "line": 303, "column": 14 }
}
}
},
"multi": {},
"transformed": {}
}
}
]
Match Object Type
Below is the equivalent TypeScript type definition of the match object.
interface Match {
text: string
range: Range
file: string // relative path to the file
// the surrounding lines of the match.
// It can be more than one line if the match spans multiple ones.
lines: string
// optional replacement if the match has a replacement
replacement?: string
replacementOffsets?: ByteOffset
metaVariables?: MetaVariables // optional metavars generated in the match
}
interface Range {
byteOffset: ByteOffset
start: Position
end: Position
}
// UTF-8 encoded byte offset
interface ByteOffset {
start: number // start is inclusive
end: number // end is exclusive
}
interface Position {
line: number // zero-based line number
column: number // zero-based column number
}
// See Pattern doc
interface MetaVariables {
single: Record<String, MetaVar>
multi: Record<String, MetaVar[]>
transformed: Record<String, String> // See Rewrite doc
}
interface MetaVar {
text: string
range: Range
}
For more information about MetaVariables
and transformed
fields, see the Pattern and Rewrite documentation.
If you are using lint rule to find matches, the generated match objects will have several more fields.
interface RuleMatch extends Match {
ruleId: string
severity: Severity
note?: string
message: string
}
enum Severity {
Error = "error",
Warning = "warning",
Info = "info",
Hint = "hint",
}
line, column, and byte offset are zero-based
The line
, column
, and byteOffset
fields are zero-based. This means that the first line, column, and byte offset are 0, not 1. The design is consistent with the LSP and tree-sitter specifications.
If you need 1-based numbers, you can use jq
to transform the output.
Consuming JSON output
ast-grep embraces the Unix philosophy of composability. The --json
flag is designed to make it easy to pipe the results to other tools.
For example, you can use jq to extract information from the results and render it in jless.
sg run -p 'Some($A)' -r 'None' --json | jq '.[].replacement' | jless
You can also see an example of using --json
flag in Vim's QuickFix window.
Output Format
By default, ast-grep prints the matches in a JSON array that is formatted with indentation and line breaks. --json
is equivalent to --json=pretty
. This makes it easy to read the output by humans. However, this might not be suitable for other programs that need to process the output from ast-grep. For example, if there are too many matches, the JSON array might be too large to fit in memory.
To avoid this problem, you can use the --json=stream
option when running ast-grep. This option will make ast-grep print each match as a separate JSON object, followed by a newline character. This way, you can stream the output to other programs that can read one object per line and parse it accordingly.
The output of --json=stream
looks like below:
$ sg -p pattern --json=stream
{"text":"Some(matched)", ... }
{"text":"Some(matched)", ... }
{"text":"Some(matched)", ... }
You can read the output line by line and process it accordingly.
--json
accepts one of the following values: pretty
, stream
, or compact
.
--json=stream
requires the equal sign
You have to use --json=<STYLE>
syntax when passing value to the json flag. A common gotcha is missing the equal sign. --json stream
is parsed as --json=pretty stream
and stream
is parsed as a directory. Only --json=stream
will work as a key-value pair.