skip to Main Content

I have a json like this

{
  "outer1": {
    "outer2": {
      "outer3": {
        "key1": "value1",
        "key2": "value2"
      }
    },
    "outer4": {
      "key1": "value1",
      "key2": "value2"
    }
  }
}

I want output to be

[outer1.outer2.outer3]
key1 = value1
key2 = value2

[outer1.outer2.outer4]
key1 = value1
key2 = value2

I tried jq -r 'to_entries|map("(.key)=(.value|tostring)")|.[]' test.json But its not what is what I want exactly

2

Answers


  1. Assuming your input looks like this:

    {
      "outer1": {
        "outer2": {
          "outer3": {
            "key1": "value1",
            "key2": "value2"
          },
          "outer4": {
            "key1": "value1",
            "key2": "value2"
          }
        }
      }
    }
    

    You could use the --stream option to read the input as a stream of path-value pairs. For instance:

    jq --stream -n '
      reduce (inputs | select(has(1))) as [$path, $val] ({};
        .[$path[:-1] | join(".")][$path[-1]] = $val
      )
    '
    
    {
      "outer1.outer2.outer3": {
        "key1": "value1",
        "key2": "value2"
      },
      "outer1.outer2.outer4": {
        "key1": "value1",
        "key2": "value2"
      }
    }
    

    Next, format this JSON according to your needs. For example using to_entries for both levels:

    jq --stream -nr '
      reduce (inputs | select(has(1))) as [$path, $val] ({};
        .[$path[:-1] | join(".")][$path[-1]] = $val
      )
      | to_entries[] | "[(.key)]", (
          .value | to_entries[] | "(.key) = (.value)"
        ), ""
    '
    
    [outer1.outer2.outer3]
    key1 = value1
    key2 = value2
    
    [outer1.outer2.outer4]
    key1 = value1
    key2 = value2
    
    
    Login or Signup to reply.
  2. My take is this:

    . as $data
    | [ path(.. | scalars) ]
    | map( . as $p | { prefix: $p[0:-1]|join("."), key: $p[-1], value: $data | getpath($p) })
    | group_by(.prefix)[]
    | "[(first.prefix)]", (.[] | "(.key)=(.value)")
    

    Basically:

    • find all scalars,
    • get the paths to these scalars (like ["outer1","outer2","outer3","key1"])
    • create intermediate representation of the path splitted into a prefix like outer1.outer2.outer3), a key (key1) and the actual value (value1)
    • group these using the prefix
    • format
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search