Convert Figma logo to code with AI

tidwall logojj

JSON Stream Editor (command line utility)

1,962
57
1,962
20

Top Related Projects

30,058

Command-line JSON processor

18,903

Terminal JSON viewer & processor

6,859

json incremental digger

13,728

Make JSON greppable!

11,663

yq is a portable command-line YAML, JSON, XML, CSV, TOML and properties processor

7,019

Select, put and delete data from JSON, TOML, YAML, XML and CSV files with a single tool. Supports conversion between formats and can be used as a Go package.

Quick Overview

JJ is a command-line JSON processor written in Go. It provides a fast and efficient way to manipulate JSON data from the terminal, offering features like querying, modifying, and formatting JSON structures.

Pros

  • Fast performance due to its implementation in Go
  • Supports a wide range of JSON manipulation operations
  • Easy-to-use command-line interface
  • Can handle large JSON files efficiently

Cons

  • Limited documentation compared to some other JSON processing tools
  • May require learning a specific syntax for complex operations
  • Not as feature-rich as some more established JSON processing libraries
  • Primarily focused on command-line usage, which may not suit all use cases

Code Examples

  1. Basic JSON querying:
package main

import "github.com/tidwall/jj"

func main() {
    json := `{"name":"John","age":30,"city":"New York"}`
    result := jj.Get(json, "name")
    println(result.String()) // Output: John
}
  1. Modifying JSON:
package main

import "github.com/tidwall/jj"

func main() {
    json := `{"name":"John","age":30,"city":"New York"}`
    result := jj.Set(json, "age", 31)
    println(result) // Output: {"name":"John","age":31,"city":"New York"}
}
  1. Deleting a JSON key:
package main

import "github.com/tidwall/jj"

func main() {
    json := `{"name":"John","age":30,"city":"New York"}`
    result := jj.Delete(json, "city")
    println(result) // Output: {"name":"John","age":30}
}

Getting Started

To use JJ in your Go project, first install it:

go get -u github.com/tidwall/jj

Then, import it in your Go code:

import "github.com/tidwall/jj"

You can now use JJ functions to process JSON data in your Go applications. For command-line usage, refer to the project's README for installation and usage instructions.

Competitor Comparisons

30,058

Command-line JSON processor

Pros of jq

  • More mature and widely adopted project with extensive documentation
  • Supports a broader range of JSON manipulation operations
  • Has a larger community and ecosystem of extensions

Cons of jq

  • Written in C, which may be less accessible for some contributors
  • Can be more complex to use for simple operations
  • Slower performance for certain operations compared to jj

Code Comparison

jq:

jq '.[] | select(.name == "Alice") | .age'

jj:

jj -i 'name == "Alice"' age

Both tools aim to process JSON data, but jq offers a more comprehensive set of features and a domain-specific language for JSON manipulation. jj, on the other hand, focuses on simplicity and speed, providing a more straightforward command-line interface for common JSON operations.

jq excels in complex JSON transformations and filtering, while jj is designed for quick and efficient JSON querying and modification. The choice between the two depends on the specific use case, with jq being more suitable for advanced JSON processing tasks and jj offering a simpler alternative for basic operations with potentially better performance.

18,903

Terminal JSON viewer & processor

Pros of fx

  • More feature-rich with interactive mode and support for various data formats
  • Actively maintained with frequent updates and contributions
  • Extensive documentation and examples for ease of use

Cons of fx

  • Larger codebase and dependencies, potentially slower startup time
  • May be overkill for simple JSON processing tasks
  • Steeper learning curve due to more advanced features

Code Comparison

fx:

fx '.[0].name' data.json
fx 'map(x => x.toUpperCase())' data.json

jj:

jj -i data.json '.[0].name'
echo '["hello", "world"]' | jj 'map(strings.upper)'

Summary

fx is a more comprehensive JSON processing tool with interactive features and support for multiple data formats. It offers a rich set of functionalities but may be more complex for simple tasks. jj, on the other hand, is a lightweight and fast JSON processor focused on simplicity and ease of use for basic JSON manipulation. The choice between the two depends on the specific requirements of the task at hand and the user's preference for simplicity versus advanced features.

6,859

json incremental digger

Pros of jid

  • Written in Go, which may be more familiar to some developers
  • Supports interactive JSON editing and manipulation
  • Provides a more user-friendly interface for JSON exploration

Cons of jid

  • Less actively maintained (last commit over 3 years ago)
  • Fewer features compared to jj
  • Limited to JSON format only

Code Comparison

jid:

func (e *Engine) Run() {
    e.initReader()
    e.printJSON()
    e.queryLoop()
}

jj:

func (j *JJ) Run() {
    j.loadInput()
    j.processCommands()
    j.outputResult()
}

Both projects aim to provide JSON processing capabilities, but they differ in their approach and feature set. jj offers a more comprehensive set of features, including support for multiple data formats (JSON, YAML, TOML), while jid focuses specifically on interactive JSON exploration.

jj is more actively maintained and has a larger community, which may lead to better long-term support and feature development. However, jid's simplicity and focus on JSON manipulation might be preferable for users who primarily work with JSON and desire a straightforward, interactive tool.

The code comparison shows that both projects have similar high-level structures for their main execution flow, but the implementation details differ based on their specific features and design choices.

13,728

Make JSON greppable!

Pros of gron

  • Simpler syntax and easier to learn for beginners
  • Better integration with Unix command-line tools
  • More focused on flattening JSON for grep-like operations

Cons of gron

  • Less powerful query capabilities compared to jj
  • Limited to JSON input, while jj supports multiple formats
  • Lacks advanced features like in-place editing and formatting

Code comparison

gron:

gron input.json | grep "name" | gron --ungron

jj:

jj -i input.json 'name'

Summary

gron is a straightforward tool for flattening JSON into greppable format, making it ideal for quick searches and simple transformations. It excels in Unix-style workflows and is easy to pick up for those familiar with command-line tools.

jj, on the other hand, offers a more comprehensive JSON manipulation toolkit with support for various input formats, advanced querying, and in-place editing. While it has a steeper learning curve, jj provides more flexibility and power for complex JSON operations.

Choose gron for simple JSON flattening and grep-like searches, or opt for jj when you need more advanced JSON manipulation capabilities and support for multiple formats.

11,663

yq is a portable command-line YAML, JSON, XML, CSV, TOML and properties processor

Pros of yq

  • Specifically designed for YAML processing, offering more YAML-centric features
  • Supports multiple input formats (JSON, YAML, XML, properties) and can convert between them
  • More extensive documentation and examples available

Cons of yq

  • Limited to YAML and related formats, less versatile for general-purpose JSON manipulation
  • May have a steeper learning curve for users not familiar with YAML-specific concepts

Code comparison

yq:

yq e '.users[] | select(.age > 30)' input.yaml

jj:

jj -i input.json '.users | map(select(.age > 30))'

Key differences

  • yq is primarily focused on YAML processing, while jj is designed for JSON manipulation
  • jj offers a more lightweight and faster solution for JSON-specific tasks
  • yq provides broader format support and conversion capabilities
  • jj's syntax is more closely aligned with jq, making it familiar to jq users
  • yq has a larger community and more frequent updates

Both tools have their strengths, with yq excelling in YAML-centric workflows and jj offering a streamlined JSON processing experience. The choice between them depends on the specific requirements of your project and the primary data format you're working with.

7,019

Select, put and delete data from JSON, TOML, YAML, XML and CSV files with a single tool. Supports conversion between formats and can be used as a Go package.

Pros of dasel

  • Supports a wider range of data formats (JSON, YAML, TOML, XML, CSV)
  • Offers both reading and writing capabilities
  • Provides a more extensive set of commands and options

Cons of dasel

  • Generally slower performance compared to jj
  • More complex syntax for some operations
  • Larger binary size and resource footprint

Code comparison

dasel:

dasel -f data.json '.users.[].name'
dasel put string -f data.json '.users.[0].name' 'John'

jj:

jj -i data.json users.*.name
echo '{"users":[{"name":"John"}]}' | jj users.0.name John

Summary

dasel offers more versatility in terms of supported formats and operations, making it suitable for complex data manipulation tasks across various file types. However, jj excels in simplicity and performance, particularly for JSON-specific operations. The choice between the two depends on the specific requirements of the project, with dasel being more feature-rich and jj being more lightweight and focused on JSON processing.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

JJ
JSON Stream Editor

JJ is a command line utility that provides a fast and simple way to retrieve or update values from JSON documents. It's powered by GJSON and SJSON under the hood.

It's fast because it avoids parsing irrelevant sections of json, skipping over values that do not apply, and aborts as soon as the target value has been found or updated.

Getting started

Install

Mac (Homebrew)

brew install tidwall/jj/jj

Build

make

Or download a pre-built binary for Linux, OSX, Windows, or FreeBSD.

Usage

$ jj -h

usage: jj [-v value] [-purOD] [-i infile] [-o outfile] keypath

examples: jj keypath                      read value from stdin
      or: jj -i infile keypath            read value from infile
      or: jj -v value keypath             edit value
      or: jj -v value -o outfile keypath  edit value and write to outfile

options:
      -v value             Edit JSON key path value
      -p                   Make json pretty, keypath is optional
      -u                   Make json ugly, keypath is optional
      -r                   Use raw values, otherwise types are auto-detected
      -n                   Do not output color or extra formatting
      -O                   Performance boost for value updates
      -D                   Delete the value at the specified key path
      -l                   Output array values on multiple lines
      -i infile            Use input file instead of stdin
      -o outfile           Use output file instead of stdout
      keypath              JSON key path (like "name.last")

Examples

Getting a value

JJ uses a path syntax for finding values.

Get a string:

$ echo '{"name":{"first":"Tom","last":"Smith"}}' | jj name.last
Smith

Get a block of JSON:

$ echo '{"name":{"first":"Tom","last":"Smith"}}' | jj name
{"first":"Tom","last":"Smith"}

Try to get a non-existent key:

$ echo '{"name":{"first":"Tom","last":"Smith"}}' | jj name.middle
null

Get the raw string value:

$ echo '{"name":{"first":"Tom","last":"Smith"}}' | jj -r name.last
"Smith"

Get an array value by index:

$ echo '{"friends":["Tom","Jane","Carol"]}' | jj friends.1
Jane

JSON Lines

There's support for JSON Lines using the .. path prefix. Which when specified, treats the multi-lined document as an array.

For example:

{"name": "Gilbert", "age": 61}
{"name": "Alexa", "age": 34}
{"name": "May", "age": 57}
..#                   >> 4
..1                   >> {"name": "Alexa", "age": 34}
..#.name              >> ["Gilbert","Alexa","May"]
..#[name="May"].age   >> 57

Setting a value

The path syntax for setting values has a couple of tiny differences than for getting values.

The -v value option is auto-detected as a Number, Boolean, Null, or String. You can override the auto-detection and input raw JSON by including the -r option. This is useful for raw JSON blocks such as object, arrays, or premarshalled strings.

Update a value:

$ echo '{"name":{"first":"Tom","last":"Smith"}}' | jj -v Andy name.first
{"name":{"first":"Andy","last":"Smith"}}

Set a new value:

$ echo '{"name":{"first":"Tom","last":"Smith"}}' | jj -v 46 age
{"age":46,"name":{"first":"Tom","last":"Smith"}}

Set a new nested value:

$ echo '{"name":{"first":"Tom","last":"Smith"}}' | jj -v relax task.today
{"task":{"today":"relax"},"name":{"first":"Tom","last":"Smith"}}

Replace an array value by index:

$ echo '{"friends":["Tom","Jane","Carol"]}' | jj -v Andy friends.1
{"friends":["Tom","Andy","Carol"]}

Append an array:

$ echo '{"friends":["Tom","Jane","Carol"]}' | jj -v Andy friends.-1
{"friends":["Tom","Andy","Carol","Andy"]}

Set an array value that's past the bounds:

$ echo '{"friends":["Tom","Jane","Carol"]}' | jj -v Andy friends.5
{"friends":["Tom","Andy","Carol",null,null,"Andy"]}

Set a raw block of JSON:

$ echo '{"name":"Carol"}' | jj -r -v '["Tom","Andy"]' friends
{"friends":["Tom","Andy"],"name":"Carol"}

Start new JSON document:

$ echo '' | jj -v 'Sam' name.first
{"name":{"first":"Sam"}}

Deleting a value

Delete a value:

$ echo '{"age":46,"name":{"first":"Tom","last":"Smith"}}' | jj -D age
{"name":{"first":"Tom","last":"Smith"}}

Delete an array value by index:

$ echo '{"friends":["Andy","Carol"]}' | jj -D friends.0
{"friends":["Carol"]}

Delete last item in array:

$ echo '{"friends":["Andy","Carol"]}' | jj -D friends.-1
{"friends":["Andy"]}

Optimistically update a value

The -O option can be used when the caller expects that a value at the specified keypath already exists.

Using this option can speed up an operation by as much as 6x, but slow down as much as 20% when the value does not exist.

For example:

echo '{"name":{"first":"Tom","last":"Smith"}}' | jj -v Tim -O name.first

The -O tells jj that the name.first likely exists so try a fasttrack operation first.

Pretty printing

The -p flag will make the output json pretty.

$ echo '{"name":{"first":"Tom","last":"Smith"}}' | jj -p name
{
  "first": "Tom",
  "last": "Smith"
}

Also the keypath is optional when the -p flag is specified, allowing for the entire json document to be made pretty.

$ echo '{"name":{"first":"Tom","last":"Smith"}}' | jj -p
{
  "name": {
    "first": "Tom",
    "last": "Smith"
  }
}

Ugly printing

The -u flag will compress the json into the fewest characters possible by squashing newlines and spaces.

Performance

A quick comparison of jj to jq. The test json file is 180MB file of 206,560 city parcels in San Francisco.

Tested on a 2015 Macbook Pro running jq 1.5 and jj 1.0.0

Get the lot number for the parcel at index 10000

jq:

$ time cat citylots.json | jq -cM .features[10000].properties.LOT_NUM
"091"

real    0m5.486s
user    0m4.870s
sys     0m0.686s

jj:

$ time cat citylots.json | jj -r features.10000.properties.LOT_NUM
"091"

real    0m0.354s
user    0m0.161s
sys     0m0.321s

Update the lot number for the parcel at index 10000

jq:

$ time cat citylots.json | jq -cM '.features[10000].properties.LOT_NUM="12A"' > /dev/null

real    0m13.579s
user    0m16.484s
sys     0m1.310s

jj:

$ time cat citylots.json | jj -O -v 12A features.10000.properties.LOT_NUM > /dev/null

real    0m0.431s
user	0m0.201s
sys     0m0.295s

Contact

Josh Baker @tidwall

License

JJ source code is available under the MIT License.