14 votes

An introduction to jq, the command-line JSON processor

1 comment

  1. wirelyre
    Link
    Great introduction, great structure. The "what I learned" sections condense the information really well. The final "what I learned" summary should be on the jq homepage. It took me a while to...

    Great introduction, great structure. The "what I learned" sections condense the information really well. The final "what I learned" summary should be on the jq homepage.

    It took me a while to figure this out: a jq filter applies to a sequence, or stream, of JSON values. At any point in a jq program there can be multiple values coming through, one after another. Not a single array, but multiple values. The filter processes them one by one.

    [0, 1]
    "a"
    
    > jq "." >
    
    [0,1]
    "a"
    

    So when you do something to an array (a single value), first you unpack it into a sequence of values:

    [0, 1, 2]
    
    > jq " .[] " >
    
    0
    1
    2
    

    … each of which goes into the next filter:

    [0, 1, 2]
    
    > jq " .[] + 1 " >
    
    1
    2
    3
    

    … which can finally be repackaged into an array.

    [0, 1, 2]
    
    > jq " [.[] + 1] " >
    
    [1,2,3]
    

    So + 1 is itself a filter that received three values in a row.

    And you might think that the select function works on arrays. Nope! It works on individual values in a stream. It emits zero or one values for each input.

    0
    1
    2
    
    > jq " select(. > 0) " >
    
    1
    2
    

    That's why select has to go inside map to process an array. You unpack the elements of an array, select some of them, then pack them back up.

    [0, 1, 2]
    > jq " map(select(. > 0)) " >
    [1,2]
    
    equivalent:
    jq " [.[] | select(. > 0)] "
    
    4 votes