Use jq to Format Certain Fields as Compact?

前端 未结 1 1088
执笔经年
执笔经年 2021-01-23 02:59

Is jq the best choice for pretty-printing arbitrary JSON?

cat my.json | jq . pretty-prints the given JSON, but expands every field on a separate line.

1条回答
  •  一生所求
    2021-01-23 03:27

    A constrained-width JSON pretty-printer could be written in jq itself. Here is a pretty-printer which illustrates how this could be done, though in its present incarnation, it is of limited usefulness.

    ppArray(indent; incr; width) will emit a stream of JSON strings that together are equivalent to the tostring value of the input. For robustness, it will always act as a pretty-printer, even if the width restriction is violated.

    If the input is an array, and if none of its elements (or recursively their elements) contains any large objects or long strings, then assuming the values of the parameters are reasonably chosen and that nesting is not too deep relative to these parameters, each emitted string should be no longer than "width".

    # indent is the initial indentation level;
    # incr is the number of spaces to add for one additional indentation level;
    # width is the target maximum width.
    #
    def ppArray(indent; incr; width):
      # The inner function produces an array of unindented strings.
      def ppArray_(incr_; width_):
        tostring as $tostring
        | if $tostring|length <= (width_ - incr_) then [$tostring]
          else reduce .[] as $i
            ([];  
             ($i|tostring) as $is
              | if length == 0 then [ $is ]
                else .[-1] as $s
                | ($s|length) as $n
                | ($is|length) as $isl
                | if $n + $isl <= (width_ - incr_)
                 then .[-1] = ($s + ", " + $is)
                  elif ($i|type) == "array"
                 then (.[-1]+=",") + [ $i | ppArray(0; incr_; width_ - incr_) ]
                  else  (.[-1]+=",") + [ $is ]
                  end 
                end )
          end;
    
        (" " * indent) as $indentation
        | if type == "array" 
          then ppArray_(incr; width - indent)
               | $indentation + "[",
               (.[] | ($indentation + "  " + . )),
               $indentation + "]"
        else $indentation + tostring
        end
    ;
    

    Example:

    [range(0;16)]
    |
    (ppArray(0; 2; 10)),
    "::",
    ([{a:1}, {b:2}, {c:3}]  | ppArray(0; 2; 10)),
    "::",
    (.[2]=[range(0;10)]) | ppArray(0; 2; 10)
    

    Invocation:

    jq -nrf pp.jq
    

    Output:

    [
      0, 1, 2, 3,
      4, 5, 6, 7,
      8, 9, 10,
      11, 12, 13,
      14, 15
    ]
    ::
    [
      {"a":1},
      {"b":2},
      {"c":3}
    ]
    ::
    [
      0, 1,
      [
        0, 1, 2,
        3, 4, 5,
        6, 7, 8,
        9
      ], 3, 4, 5,
      6, 7, 8, 9,
      10, 11, 12,
      13, 14, 15
    ]
    

    0 讨论(0)
提交回复
热议问题