Java-Web:Using jq to process Json

From Juneday education
Jump to: navigation, search

Using jq to process Json

Work in progress

We'll show you some basics of using jq to verify and manipulate Json on the command line.

Verifying and pretty printing

The simplest thing you can do with jq is to let it validate a stream of Json text, and as a result also pretty print it.

To do so, pipe the Json text to jq like this:

$ GET https://player.vimeo.com/video/200221371/config|jq '.'

Expand using link to the right to see the full result (it's quite long).

{
  "cdn_url": "https://f.vimeocdn.com",
  "vimeo_api_url": "api.vimeo.com",
  "request": {
    "files": {
      "dash": {
        "separate_av": true,
        "streams": [
          {
            "profile": 164,
            "quality": "360p",
            "id": 676097494,
            "fps": 28
          },
          {
            "profile": 119,
            "quality": "1080p",
            "id": 676097496,
            "fps": 28
          },
          {
            "profile": 174,
            "quality": "720p",
            "id": 676097495,
            "fps": 28
          },
          {
            "profile": 165,
            "quality": "540p",
            "id": 676097487,
            "fps": 28
          }
        ],
        "cdns": {
          "akfire_interconnect_quic": {
            "url": "https://172skyfiregce-vimeo.akamaized.net/exp=1543491593~acl=%2F200221371%2F%2A~hmac=e756c2c617a557b605beb18b7ae841589691b758dab504c903dc242d8e80e2e5/200221371/sep/video/676097494,676097496,676097495,676097487/master.json?base64_init=1",
            "origin": "gcs"
          },
          "fastly_skyfire": {
            "url": "https://skyfire.vimeocdn.com/1543491593-0xd14063234a887465406613152f6997cab00ca448/200221371/sep/video/676097494,676097496,676097495,676097487/master.json?base64_init=1",
            "origin": "gcs"
          }
        },
        "default_cdn": "akfire_interconnect_quic"
      },
      "hls": {
        "separate_av": false,
        "default_cdn": "akfire_interconnect_quic",
        "cdns": {
          "akfire_interconnect_quic": {
            "url": "https://172skyfiregce-vimeo.akamaized.net/exp=1543491593~acl=%2F200221371%2F%2A~hmac=e756c2c617a557b605beb18b7ae841589691b758dab504c903dc242d8e80e2e5/200221371/video/676097494,676097496,676097495,676097487/master.m3u8",
            "origin": "gcs"
          },
          "fastly_skyfire": {
            "url": "https://skyfire.vimeocdn.com/1543491593-0xd14063234a887465406613152f6997cab00ca448/200221371/video/676097494,676097496,676097495,676097487/master.m3u8",
            "origin": "gcs"
          }
        }
      },
      "progressive": [
        {
          "profile": 119,
          "width": 1728,
          "mime": "video/mp4",
          "fps": 28,
          "url": "https://gcs-vimeo.akamaized.net/exp=1543491593~acl=%2A%2F676097496.mp4%2A~hmac=091d5ef8d5f20471bb73a24bc0609f92d4207824f353b74ee7957a003f25d1c4/vimeo-prod-skyfire-std-us/01/44/8/200221371/676097496.mp4",
          "cdn": "akamai_interconnect",
          "quality": "1080p",
          "id": 676097496,
          "origin": "gcs",
          "height": 1080
        },
        {
          "profile": 174,
          "width": 1152,
          "mime": "video/mp4",
          "fps": 28,
          "url": "https://gcs-vimeo.akamaized.net/exp=1543491593~acl=%2A%2F676097495.mp4%2A~hmac=813a2b9d9d0d465606790f7c2dbb4b5618d3f3018d7cd38f214e43260109d95b/vimeo-prod-skyfire-std-us/01/44/8/200221371/676097495.mp4",
          "cdn": "akamai_interconnect",
          "quality": "720p",
          "id": 676097495,
          "origin": "gcs",
          "height": 720
        },
        {
          "profile": 164,
          "width": 576,
          "mime": "video/mp4",
          "fps": 28,
          "url": "https://gcs-vimeo.akamaized.net/exp=1543491593~acl=%2A%2F676097494.mp4%2A~hmac=0703cf5f242edbe5ccf48dd3eb3298124e08ead4ca5770ce64f27e2a6498b3e1/vimeo-prod-skyfire-std-us/01/44/8/200221371/676097494.mp4",
          "cdn": "akamai_interconnect",
          "quality": "360p",
          "id": 676097494,
          "origin": "gcs",
          "height": 360
        },
        {
          "profile": 165,
          "width": 864,
          "mime": "video/mp4",
          "fps": 28,
          "url": "https://gcs-vimeo.akamaized.net/exp=1543491593~acl=%2A%2F676097487.mp4%2A~hmac=000be1a094613dd5c575cb282fd116758a53ac56e2675f2e75aedc939824f6f2/vimeo-prod-skyfire-std-us/01/44/8/200221371/676097487.mp4",
          "cdn": "akamai_interconnect",
          "quality": "540p",
          "id": 676097487,
          "origin": "gcs",
          "height": 540
        }
      ]
    },
    "lang": "en",
    "sentry": {
      "url": "https://6f5f8e1cecfa40fb850f578b69fc1705@sentry.io/1297650",
      "enabled": true,
      "debug_enabled": true,
      "debug_intent": 0
    },
    "ab_tests": {
      "chromecast": {
        "data": {},
        "group": false
      }
    },
    "referrer": null,
    "cookie_domain": ".vimeo.com",
    "timestamp": 1543487693,
    "gc_debug": {
      "bucket": "vimeo-player-debug"
    },
    "expires": 3600,
    "currency": "SEK",
    "session": "5429315dfc11ed6e66844abe1110f2fecb6c14f41543487693",
    "cookie": {
      "scaling": 1,
      "volume": 1,
      "quality": null,
      "hd": 0,
      "captions": null
    },
    "build": {
      "player": "",
      "backend": "1.0.26",
      "js": "3.6.0"
    },
    "urls": {
      "barebone_js": "https://f.vimeocdn.com/p/3.6.0/js/barebone.js",
      "zeroclip_swf": "https://f.vimeocdn.com/p/external/zeroclipboard/ZeroClipboard.swf",
      "fresnel": "https://fresnel.vimeocdn.com/add/player-stats",
      "js": "https://f.vimeocdn.com/p/3.6.0/js/player.js",
      "proxy": "https://player.vimeo.com/static/proxy.html",
      "chromeless_css": "https://f.vimeocdn.com/p/3.6.0/css/chromeless.css",
      "three_js": "https://f.vimeocdn.com/p/external/three.rvimeo.min.js",
      "mux_url": "https://f.vimeocdn.com/p/external/mux.js",
      "vuid_js": "https://f.vimeocdn.com/js_opt/modules/utils/vuid.min.js",
      "chromeless_js": "https://f.vimeocdn.com/p/3.6.0/js/chromeless.js",
      "zeroclip_js": "https://f.vimeocdn.com/p/external/zeroclipboard/ZeroClipboard-patch.js",
      "css": "https://f.vimeocdn.com/p/3.6.0/css/player.css"
    },
    "signature": "a5375dc9d2b4fb9c1d0c83a0fc856f7c",
    "flags": {
      "preload_video": "metadata_on_hover",
      "plays": 1,
      "log_to_es": 0,
      "webp": 0,
      "dnt": 0,
      "partials": 1,
      "autohide_controls": 0
    },
    "country": "SE"
  },
  "player_url": "player.vimeo.com",
  "video": {
    "rating": {
      "id": 6
    },
    "version": {
      "current": null,
      "available": null
    },
    "height": 1080,
    "duration": 579,
    "thumbs": {
      "1280": "https://i.vimeocdn.com/video/613668912_1280.jpg",
      "960": "https://i.vimeocdn.com/video/613668912_960.jpg",
      "640": "https://i.vimeocdn.com/video/613668912_640.jpg",
      "base": "https://i.vimeocdn.com/video/613668912"
    },
    "owner": {
      "account_type": "plus",
      "name": "Rikard and Henrik",
      "img": "https://i.vimeocdn.com/portrait/14693817_60x60.jpg",
      "url": "https://vimeo.com/user52531669",
      "img_2x": "https://i.vimeocdn.com/portrait/14693817_120x120.jpg",
      "id": 52531669
    },
    "file_codecs": {
      "hevc": {
        "hdr": [],
        "sdr": []
      },
      "avc": [
        676097496,
        676097495,
        676097494,
        676097487
      ]
    },
    "id": 200221371,
    "embed_code": "<iframe src=\"https://player.vimeo.com/video/200221371\" width=\"640\" height=\"400\" frameborder=\"0\" allowfullscreen></iframe>",
    "title": "Introduktion till Winstone och Servlets del 4/6",
    "share_url": "https://vimeo.com/200221371",
    "width": 1728,
    "embed_permission": "public",
    "fps": 28.93,
    "spatial": 0,
    "live_event": null,
    "allow_hd": 1,
    "hd": 1,
    "lang": "sv",
    "default_to_hd": 0,
    "url": "https://vimeo.com/200221371",
    "privacy": "anybody",
    "bypass_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjbGlwX2lkIjoyMDAyMjEzNzEsImV4cCI6MTU0MzQ4OTQ2NX0.1CK4nfPYwDdSfe6fN6iqlxQcm_k5KN1Pfi9QnBSJsXc",
    "unlisted_hash": null
  },
  "user": {
    "vimeo_api_interaction_tokens": null,
    "liked": 0,
    "account_type": "none",
    "vimeo_api_client_token": null,
    "progress": 0,
    "owner": 0,
    "watch_later": 0,
    "logged_in": 0,
    "id": 0,
    "mod": 0
  },
  "embed": {
    "autopause": 1,
    "playsinline": 1,
    "settings": {
      "fullscreen": 1,
      "byline": 1,
      "like": 1,
      "playbar": 1,
      "title": 1,
      "color": 0,
      "speed": 0,
      "watch_later": 1,
      "share": 1,
      "scaling": 1,
      "spatial_compass": 1,
      "collections": 0,
      "info_on_pause": 0,
      "portrait": 1,
      "logo": 1,
      "embed": 1,
      "badge": 0,
      "spatial_label": 1,
      "volume": 1
    },
    "color": "00adef",
    "on_site": 0,
    "app_id": "",
    "muted": 0,
    "dnt": 0,
    "player_id": "",
    "api": 3,
    "editor": false,
    "context": "embed.main",
    "time": 0,
    "outro": "videos",
    "log_plays": 1,
    "quality": null,
    "transparent": 1,
    "loop": 0,
    "autoplay": 0
  },
  "view": 1,
  "vimeo_url": "vimeo.com"
}

The result is quite long. It contains a "request" object, some data, a "video" object, and some more stuff. Let's say we are interested only in the "video" object.

We'll tell jq to only keep the video object like this:

$ GET https://player.vimeo.com/video/200221371/config|jq '.video'

The result is now a lot shorter, but still contains more than we are interested in:

{
  "rating": {
    "id": 6
  },
  "version": {
    "current": null,
    "available": null
  },
  "height": 1080,
  "duration": 579,
  "thumbs": {
    "1280": "https://i.vimeocdn.com/video/613668912_1280.jpg",
    "960": "https://i.vimeocdn.com/video/613668912_960.jpg",
    "640": "https://i.vimeocdn.com/video/613668912_640.jpg",
    "base": "https://i.vimeocdn.com/video/613668912"
  },
  "owner": {
    "account_type": "plus",
    "name": "Rikard and Henrik",
    "img": "https://i.vimeocdn.com/portrait/14693817_60x60.jpg",
    "url": "https://vimeo.com/user52531669",
    "img_2x": "https://i.vimeocdn.com/portrait/14693817_120x120.jpg",
    "id": 52531669
  },
  "file_codecs": {
    "hevc": {
      "hdr": [],
      "sdr": []
    },
    "avc": [
      676097496,
      676097495,
      676097494,
      676097487
    ]
  },
  "id": 200221371,
  "embed_code": "<iframe src=\"https://player.vimeo.com/video/200221371\" width=\"640\" height=\"400\" frameborder=\"0\" allowfullscreen></iframe>",
  "title": "Introduktion till Winstone och Servlets del 4/6",
  "share_url": "https://vimeo.com/200221371",
  "width": 1728,
  "embed_permission": "public",
  "fps": 28.93,
  "spatial": 0,
  "live_event": null,
  "allow_hd": 1,
  "hd": 1,
  "lang": "sv",
  "default_to_hd": 0,
  "url": "https://vimeo.com/200221371",
  "privacy": "anybody",
  "bypass_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjbGlwX2lkIjoyMDAyMjEzNzEsImV4cCI6MTU0MzQ4OTQ2NX0.1CK4nfPYwDdSfe6fN6iqlxQcm_k5KN1Pfi9QnBSJsXc",
  "unlisted_hash": null
}

So, let's tell jq that we are most interested in the following attributes:

  • title
  • duration (in seconds)
  • lang (language abbreviation)
  • share_url
GET https://player.vimeo.com/video/200221371/config|jq '.video.title, .video.duration, .video.lang, .video.share_url'
"Introduktion till Winstone och Servlets del 4/6"
579
"sv"
"https://vimeo.com/200221371"

Now we got the data as quoted string and unquoted numbers.

What if we want to get it as Json?

We can do that like this:

$ GET https://player.vimeo.com/video/200221371/config|jq '{title: .video.title, duration: .video.duration, lang: .video.lang, share_url: .video.share_url}'
{
  "title": "Introduktion till Winstone och Servlets del 4/6",
  "duration": 579,
  "lang": "sv",
  "share_url": "https://vimeo.com/200221371"
}

Let's say that we also want to include some stuff from an object nested inside "video", like .owner.name :

    "owner": {
      "account_type": "plus",
      "name": "Rikard and Henrik",
      "img": "https://i.vimeocdn.com/portrait/14693817_60x60.jpg",
      "url": "https://vimeo.com/user52531669",
      "img_2x": "https://i.vimeocdn.com/portrait/14693817_120x120.jpg",
      "id": 52531669
    }

Then, we'd have to qualify the path to the name attribute via first .video then .owner, then .name :

$ GET https://player.vimeo.com/video/200221371/config|jq '{title: .video.title, duration: .video.duration, lang: .video.lang, share_url: .video.share_url, owner_name: .video.owner.name}'
{
  "title": "Introduktion till Winstone och Servlets del 4/6",
  "duration": 579,
  "lang": "sv",
  "share_url": "https://vimeo.com/200221371",
  "owner_name": "Rikard and Henrik"
}

We made up the attibute key "owner_name". We did it in the jq argument, in the part reading owner_name: .video.owner.name at the end.

Arrays

Let's look at the following array from the example json:

  "request": {
    "files": {
      "dash": {
        "separate_av": true,
        "streams": [
          {
            "profile": 164,
            "quality": "360p",
            "id": 676097494,
            "fps": 28
          },
          {
            "profile": 119,
            "quality": "1080p",
            "id": 676097496,
            "fps": 28
          },
          {
            "profile": 174,
            "quality": "720p",
            "id": 676097495,
            "fps": 28
          },
          {
            "profile": 165,
            "quality": "540p",
            "id": 676097487,
            "fps": 28
          }
        ]

The path to the streams array is:

.request.files.dash.streams[].

Let's see how we can extract only this array:

$ GET https://player.vimeo.com/video/200221371/config|jq '.request.files.dash.streams[]'
{
  "profile": 164,
  "quality": "360p",
  "id": 676097494,
  "fps": 28
}
{
  "profile": 119,
  "quality": "1080p",
  "id": 676097496,
  "fps": 28
}
{
  "profile": 174,
  "quality": "720p",
  "id": 676097495,
  "fps": 28
}
{
  "profile": 165,
  "quality": "540p",
  "id": 676097487,
  "fps": 28
}

Now, what if we are only interested in the first element of the array (the first object inside it)?

We can index an array, pretty much like we can in most programming languages. Array indices start at 0 (except for moronic languages like VB).

$ GET https://player.vimeo.com/video/200221371/config|jq '.request.files.dash.streams[0]'
{
  "profile": 164,
  "quality": "360p",
  "id": 676097494,
  "fps": 28
}

We can even filter out a specific array element, using select. Let's say we are only interested in stream elements with "quality": "540p":

$ GET https://player.vimeo.com/video/200221371/config|jq '.request.files.dash.streams[]| select(.quality == "540p")'
{
  "profile": 165,
  "quality": "540p",
  "id": 676097487,
  "fps": 28
}

That's pretty much all we wanted to share with you. Install jq if you haven't already done so, and read the tutorial and manual in the links section below.

Bonus - Script to get jq-paths from Json

The script tries to create paths to all elements in a Json, so that you get an overview of the Json structure.

We think the script is good enough™.

Expand using link to the right to see the full test runs (it's quite long).

Example runs:

$ GET https://player.vimeo.com/video/200221371/config | ./jq-paths.sh

."cdn_url"
."vimeo_api_url"
."request"
."request"."files"
."request"."files"."dash"
."request"."files"."dash"."separate_av"
."request"."files"."dash"."streams"
."request"."files"."dash"."streams"[0]
."request"."files"."dash"."streams"[0]."profile"
."request"."files"."dash"."streams"[0]."quality"
."request"."files"."dash"."streams"[0]."id"
."request"."files"."dash"."streams"[0]."fps"
."request"."files"."dash"."streams"[1]
."request"."files"."dash"."streams"[1]."profile"
."request"."files"."dash"."streams"[1]."quality"
."request"."files"."dash"."streams"[1]."id"
."request"."files"."dash"."streams"[1]."fps"
."request"."files"."dash"."streams"[2]
."request"."files"."dash"."streams"[2]."profile"
."request"."files"."dash"."streams"[2]."quality"
."request"."files"."dash"."streams"[2]."id"
."request"."files"."dash"."streams"[2]."fps"
."request"."files"."dash"."streams"[3]
."request"."files"."dash"."streams"[3]."profile"
."request"."files"."dash"."streams"[3]."quality"
."request"."files"."dash"."streams"[3]."id"
."request"."files"."dash"."streams"[3]."fps"
."request"."files"."dash"."cdns"
."request"."files"."dash"."cdns"."akfire_interconnect_quic"
."request"."files"."dash"."cdns"."akfire_interconnect_quic"."url"
."request"."files"."dash"."cdns"."akfire_interconnect_quic"."origin"
."request"."files"."dash"."cdns"."fastly_skyfire"
."request"."files"."dash"."cdns"."fastly_skyfire"."url"
."request"."files"."dash"."cdns"."fastly_skyfire"."origin"
."request"."files"."dash"."default_cdn"
."request"."files"."hls"
."request"."files"."hls"."separate_av"
."request"."files"."hls"."default_cdn"
."request"."files"."hls"."cdns"
."request"."files"."hls"."cdns"."akfire_interconnect_quic"
."request"."files"."hls"."cdns"."akfire_interconnect_quic"."url"
."request"."files"."hls"."cdns"."akfire_interconnect_quic"."origin"
."request"."files"."hls"."cdns"."fastly_skyfire"
."request"."files"."hls"."cdns"."fastly_skyfire"."url"
."request"."files"."hls"."cdns"."fastly_skyfire"."origin"
."request"."files"."progressive"
."request"."files"."progressive"[0]
."request"."files"."progressive"[0]."profile"
."request"."files"."progressive"[0]."width"
."request"."files"."progressive"[0]."mime"
."request"."files"."progressive"[0]."fps"
."request"."files"."progressive"[0]."url"
."request"."files"."progressive"[0]."cdn"
."request"."files"."progressive"[0]."quality"
."request"."files"."progressive"[0]."id"
."request"."files"."progressive"[0]."origin"
."request"."files"."progressive"[0]."height"
."request"."files"."progressive"[1]
."request"."files"."progressive"[1]."profile"
."request"."files"."progressive"[1]."width"
."request"."files"."progressive"[1]."mime"
."request"."files"."progressive"[1]."fps"
."request"."files"."progressive"[1]."url"
."request"."files"."progressive"[1]."cdn"
."request"."files"."progressive"[1]."quality"
."request"."files"."progressive"[1]."id"
."request"."files"."progressive"[1]."origin"
."request"."files"."progressive"[1]."height"
."request"."files"."progressive"[2]
."request"."files"."progressive"[2]."profile"
."request"."files"."progressive"[2]."width"
."request"."files"."progressive"[2]."mime"
."request"."files"."progressive"[2]."fps"
."request"."files"."progressive"[2]."url"
."request"."files"."progressive"[2]."cdn"
."request"."files"."progressive"[2]."quality"
."request"."files"."progressive"[2]."id"
."request"."files"."progressive"[2]."origin"
."request"."files"."progressive"[2]."height"
."request"."files"."progressive"[3]
."request"."files"."progressive"[3]."profile"
."request"."files"."progressive"[3]."width"
."request"."files"."progressive"[3]."mime"
."request"."files"."progressive"[3]."fps"
."request"."files"."progressive"[3]."url"
."request"."files"."progressive"[3]."cdn"
."request"."files"."progressive"[3]."quality"
."request"."files"."progressive"[3]."id"
."request"."files"."progressive"[3]."origin"
."request"."files"."progressive"[3]."height"
."request"."lang"
."request"."sentry"
."request"."sentry"."url"
."request"."sentry"."enabled"
."request"."sentry"."debug_enabled"
."request"."sentry"."debug_intent"
."request"."ab_tests"
."request"."ab_tests"."chromecast"
."request"."ab_tests"."chromecast"."data"
."request"."ab_tests"."chromecast"."group"
."request"."cookie_domain"
."request"."timestamp"
."request"."gc_debug"
."request"."gc_debug"."bucket"
."request"."expires"
."request"."currency"
."request"."session"
."request"."cookie"
."request"."cookie"."scaling"
."request"."cookie"."volume"
."request"."cookie"."hd"
."request"."build"
."request"."build"."player"
."request"."build"."backend"
."request"."build"."js"
."request"."urls"
."request"."urls"."barebone_js"
."request"."urls"."zeroclip_swf"
."request"."urls"."fresnel"
."request"."urls"."js"
."request"."urls"."proxy"
."request"."urls"."chromeless_css"
."request"."urls"."three_js"
."request"."urls"."mux_url"
."request"."urls"."vuid_js"
."request"."urls"."chromeless_js"
."request"."urls"."zeroclip_js"
."request"."urls"."css"
."request"."signature"
."request"."flags"
."request"."flags"."preload_video"
."request"."flags"."plays"
."request"."flags"."log_to_es"
."request"."flags"."webp"
."request"."flags"."dnt"
."request"."flags"."partials"
."request"."flags"."autohide_controls"
."request"."country"
."player_url"
."video"
."video"."rating"
."video"."rating"."id"
."video"."version"
."video"."height"
."video"."duration"
."video"."thumbs"
."video"."thumbs"."1280"
."video"."thumbs"."960"
."video"."thumbs"."640"
."video"."thumbs"."base"
."video"."owner"
."video"."owner"."account_type"
."video"."owner"."name"
."video"."owner"."img"
."video"."owner"."url"
."video"."owner"."img_2x"
."video"."owner"."id"
."video"."file_codecs"
."video"."file_codecs"."hevc"
."video"."file_codecs"."hevc"."hdr"
."video"."file_codecs"."hevc"."sdr"
."video"."file_codecs"."avc"
."video"."file_codecs"."avc"[0]
."video"."file_codecs"."avc"[1]
."video"."file_codecs"."avc"[2]
."video"."file_codecs"."avc"[3]
."video"."id"
."video"."embed_code"
."video"."title"
."video"."share_url"
."video"."width"
."video"."embed_permission"
."video"."fps"
."video"."spatial"
."video"."allow_hd"
."video"."hd"
."video"."lang"
."video"."default_to_hd"
."video"."url"
."video"."privacy"
."video"."bypass_token"
."user"
."user"."liked"
."user"."account_type"
."user"."progress"
."user"."owner"
."user"."watch_later"
."user"."logged_in"
."user"."id"
."user"."mod"
."embed"
."embed"."autopause"
."embed"."playsinline"
."embed"."settings"
."embed"."settings"."fullscreen"
."embed"."settings"."byline"
."embed"."settings"."like"
."embed"."settings"."playbar"
."embed"."settings"."title"
."embed"."settings"."color"
."embed"."settings"."speed"
."embed"."settings"."watch_later"
."embed"."settings"."share"
."embed"."settings"."scaling"
."embed"."settings"."spatial_compass"
."embed"."settings"."collections"
."embed"."settings"."info_on_pause"
."embed"."settings"."portrait"
."embed"."settings"."logo"
."embed"."settings"."embed"
."embed"."settings"."badge"
."embed"."settings"."spatial_label"
."embed"."settings"."volume"
."embed"."color"
."embed"."on_site"
."embed"."app_id"
."embed"."muted"
."embed"."dnt"
."embed"."player_id"
."embed"."api"
."embed"."editor"
."embed"."context"
."embed"."time"
."embed"."outro"
."embed"."log_plays"
."embed"."transparent"
."embed"."loop"
."embed"."autoplay"
."view"
."vimeo_url"

OK

$ cat servlet.json | ./jq-paths.sh

."web-app"
."web-app"."servlet"
."web-app"."servlet"[0]
."web-app"."servlet"[0]."servlet-name"
."web-app"."servlet"[0]."servlet-class"
."web-app"."servlet"[0]."init-param"
."web-app"."servlet"[0]."init-param"."configGlossary:installationAt"
."web-app"."servlet"[0]."init-param"."configGlossary:adminEmail"
."web-app"."servlet"[0]."init-param"."configGlossary:poweredBy"
."web-app"."servlet"[0]."init-param"."configGlossary:poweredByIcon"
."web-app"."servlet"[0]."init-param"."configGlossary:staticPath"
."web-app"."servlet"[0]."init-param"."templateProcessorClass"
."web-app"."servlet"[0]."init-param"."templateLoaderClass"
."web-app"."servlet"[0]."init-param"."templatePath"
."web-app"."servlet"[0]."init-param"."templateOverridePath"
."web-app"."servlet"[0]."init-param"."defaultListTemplate"
."web-app"."servlet"[0]."init-param"."defaultFileTemplate"
."web-app"."servlet"[0]."init-param"."useJSP"
."web-app"."servlet"[0]."init-param"."jspListTemplate"
."web-app"."servlet"[0]."init-param"."jspFileTemplate"
."web-app"."servlet"[0]."init-param"."cachePackageTagsTrack"
."web-app"."servlet"[0]."init-param"."cachePackageTagsStore"
."web-app"."servlet"[0]."init-param"."cachePackageTagsRefresh"
."web-app"."servlet"[0]."init-param"."cacheTemplatesTrack"
."web-app"."servlet"[0]."init-param"."cacheTemplatesStore"
."web-app"."servlet"[0]."init-param"."cacheTemplatesRefresh"
."web-app"."servlet"[0]."init-param"."cachePagesTrack"
."web-app"."servlet"[0]."init-param"."cachePagesStore"
."web-app"."servlet"[0]."init-param"."cachePagesRefresh"
."web-app"."servlet"[0]."init-param"."cachePagesDirtyRead"
."web-app"."servlet"[0]."init-param"."searchEngineListTemplate"
."web-app"."servlet"[0]."init-param"."searchEngineFileTemplate"
."web-app"."servlet"[0]."init-param"."searchEngineRobotsDb"
."web-app"."servlet"[0]."init-param"."useDataStore"
."web-app"."servlet"[0]."init-param"."dataStoreClass"
."web-app"."servlet"[0]."init-param"."redirectionClass"
."web-app"."servlet"[0]."init-param"."dataStoreName"
."web-app"."servlet"[0]."init-param"."dataStoreDriver"
."web-app"."servlet"[0]."init-param"."dataStoreUrl"
."web-app"."servlet"[0]."init-param"."dataStoreUser"
."web-app"."servlet"[0]."init-param"."dataStorePassword"
."web-app"."servlet"[0]."init-param"."dataStoreTestQuery"
."web-app"."servlet"[0]."init-param"."dataStoreLogFile"
."web-app"."servlet"[0]."init-param"."dataStoreInitConns"
."web-app"."servlet"[0]."init-param"."dataStoreMaxConns"
."web-app"."servlet"[0]."init-param"."dataStoreConnUsageLimit"
."web-app"."servlet"[0]."init-param"."dataStoreLogLevel"
."web-app"."servlet"[0]."init-param"."maxUrlLength"
."web-app"."servlet"[1]
."web-app"."servlet"[1]."servlet-name"
."web-app"."servlet"[1]."servlet-class"
."web-app"."servlet"[1]."init-param"
."web-app"."servlet"[1]."init-param"."mailHost"
."web-app"."servlet"[1]."init-param"."mailHostOverride"
."web-app"."servlet"[2]
."web-app"."servlet"[2]."servlet-name"
."web-app"."servlet"[2]."servlet-class"
."web-app"."servlet"[3]
."web-app"."servlet"[3]."servlet-name"
."web-app"."servlet"[3]."servlet-class"
."web-app"."servlet"[4]
."web-app"."servlet"[4]."servlet-name"
."web-app"."servlet"[4]."servlet-class"
."web-app"."servlet"[4]."init-param"
."web-app"."servlet"[4]."init-param"."templatePath"
."web-app"."servlet"[4]."init-param"."log"
."web-app"."servlet"[4]."init-param"."logLocation"
."web-app"."servlet"[4]."init-param"."logMaxSize"
."web-app"."servlet"[4]."init-param"."dataLog"
."web-app"."servlet"[4]."init-param"."dataLogLocation"
."web-app"."servlet"[4]."init-param"."dataLogMaxSize"
."web-app"."servlet"[4]."init-param"."removePageCache"
."web-app"."servlet"[4]."init-param"."removeTemplateCache"
."web-app"."servlet"[4]."init-param"."fileTransferFolder"
."web-app"."servlet"[4]."init-param"."lookInContext"
."web-app"."servlet"[4]."init-param"."adminGroupID"
."web-app"."servlet"[4]."init-param"."betaServer"
."web-app"."servlet-mapping"
."web-app"."servlet-mapping"."cofaxCDS"
."web-app"."servlet-mapping"."cofaxEmail"
."web-app"."servlet-mapping"."cofaxAdmin"
."web-app"."servlet-mapping"."fileServlet"
."web-app"."servlet-mapping"."cofaxTools"
."web-app"."taglib"
."web-app"."taglib"."taglib-uri"
."web-app"."taglib"."taglib-location"

OK

$ cat svg.json | jq '.'
{
  "menu": {
    "header": "SVG Viewer",
    "items": [
      {
        "id": "Open"
      },
      {
        "id": "OpenNew",
        "label": "Open New"
      },
      null,
      {
        "id": "ZoomIn",
        "label": "Zoom In"
      },
      {
        "id": "ZoomOut",
        "label": "Zoom Out"
      },
      {
        "id": "OriginalView",
        "label": "Original View"
      },
      null,
      {
        "id": "Quality"
      },
      {
        "id": "Pause"
      },
      {
        "id": "Mute"
      },
      null,
      {
        "id": "Find",
        "label": "Find..."
      },
      {
        "id": "FindAgain",
        "label": "Find Again"
      },
      {
        "id": "Copy"
      },
      {
        "id": "CopyAgain",
        "label": "Copy Again"
      },
      {
        "id": "CopySVG",
        "label": "Copy SVG"
      },
      {
        "id": "ViewSVG",
        "label": "View SVG"
      },
      {
        "id": "ViewSource",
        "label": "View Source"
      },
      {
        "id": "SaveAs",
        "label": "Save As"
      },
      null,
      {
        "id": "Help"
      },
      {
        "id": "About",
        "label": "About Adobe CVG Viewer..."
      }
    ]
  }
}

$ cat svg.json | ./jq-paths.sh 

."menu"
."menu"."header"
."menu"."items"
."menu"."items"[0]
."menu"."items"[0]."id"
."menu"."items"[1]
."menu"."items"[1]."id"
."menu"."items"[1]."label"
."menu"."items"[3]
."menu"."items"[3]."id"
."menu"."items"[3]."label"
."menu"."items"[4]
."menu"."items"[4]."id"
."menu"."items"[4]."label"
."menu"."items"[5]
."menu"."items"[5]."id"
."menu"."items"[5]."label"
."menu"."items"[7]
."menu"."items"[7]."id"
."menu"."items"[8]
."menu"."items"[8]."id"
."menu"."items"[9]
."menu"."items"[9]."id"
."menu"."items"[11]
."menu"."items"[11]."id"
."menu"."items"[11]."label"
."menu"."items"[12]
."menu"."items"[12]."id"
."menu"."items"[12]."label"
."menu"."items"[13]
."menu"."items"[13]."id"
."menu"."items"[14]
."menu"."items"[14]."id"
."menu"."items"[14]."label"
."menu"."items"[15]
."menu"."items"[15]."id"
."menu"."items"[15]."label"
."menu"."items"[16]
."menu"."items"[16]."id"
."menu"."items"[16]."label"
."menu"."items"[17]
."menu"."items"[17]."id"
."menu"."items"[17]."label"
."menu"."items"[18]
."menu"."items"[18]."id"
."menu"."items"[18]."label"
."menu"."items"[20]
."menu"."items"[20]."id"
."menu"."items"[21]
."menu"."items"[21]."id"
."menu"."items"[21]."label"

Skips null elements in array, but OK

$ cat quiz.json
{
    "quiz": {
        "sport": {
            "q1": {
                "question": "Which one is correct team name in NBA?",
                "options": [
                    "New York Bulls",
                    "Los Angeles Kings",
                    "Golden State Warriros",
                    "Huston Rocket"
                ],
                "answer": "Huston Rocket"
            }
        },
        "maths": {
            "q1": {
                "question": "5 + 7 = ?",
                "options": [
                    "10",
                    "11",
                    "12",
                    "13"
                ],
                "answer": "12"
            },
            "q2": {
                "question": "12 - 8 = ?",
                "options": [
                    "1",
                    "2",
                    "3",
                    "4"
                ],
                "answer": "4"
            }
        }
    }
}

$ cat quiz.json | ./jq-paths.sh 

."quiz"
."quiz"."sport"
."quiz"."sport"."q1"
."quiz"."sport"."q1"."question"
."quiz"."sport"."q1"."options"
."quiz"."sport"."q1"."options"[0]
."quiz"."sport"."q1"."options"[1]
."quiz"."sport"."q1"."options"[2]
."quiz"."sport"."q1"."options"[3]
."quiz"."sport"."q1"."answer"
."quiz"."maths"
."quiz"."maths"."q1"
."quiz"."maths"."q1"."question"
."quiz"."maths"."q1"."options"
."quiz"."maths"."q1"."options"[0]
."quiz"."maths"."q1"."options"[1]
."quiz"."maths"."q1"."options"[2]
."quiz"."maths"."q1"."options"[3]
."quiz"."maths"."q1"."answer"
."quiz"."maths"."q2"
."quiz"."maths"."q2"."question"
."quiz"."maths"."q2"."options"
."quiz"."maths"."q2"."options"[0]
."quiz"."maths"."q2"."options"[1]
."quiz"."maths"."q2"."options"[2]
."quiz"."maths"."q2"."options"[3]
."quiz"."maths"."q2"."answer"

OK

$ cat beer-arr.json 
[
{
  "id": 222,
  "name": "Dog E",
  "tagline": "Ninth Anniversary Imperial Stout.",
  "first_brewed": "06/2016",
  "description": "Dog E is a very special beer. This beer commemorates our 9th year in 2016. This beer originally appeared as AB:04 in 2010, perhaps the most sought after beer we ever brewed. Dog E is a 16.1% Imperial Stout brewed with copious amounts of dark malts, pure cacao and coffee, balanced by the subtle addition of naga chili, and barrel-aged. Perfect for ageing in your cellar, or drinking fresh if you’re lucky enough to get your paws on a bottle.",
  "image_url": "https://images.punkapi.com/v2/222.png",
  "abv": 16.1,
  "ibu": 100,
  "target_fg": 1125,
  "target_og": 1015,
  "ebc": 500,
  "srm": 254,
  "ph": 4.4,
  "attenuation_level": 84,
  "volume": {
    "value": 20,
    "unit": "liters"
  },
  "boil_volume": {
    "value": 25,
    "unit": "liters"
  },
  "method": {
    "mash_temp": [
      {
        "temp": {
          "value": 63,
          "unit": "celsius"
        },
        "duration": 90
      }
    ],
    "fermentation": {
      "temp": {
        "value": 21,
        "unit": "celsius"
      }
    },
    "twist": "5g Habanero and 3g lemon drop chili in FV"
  },
  "ingredients": {
    "malt": [
      {
        "name": "Pale Ale",
        "amount": {
          "value": 7.5,
          "unit": "kilograms"
        }
      },
      {
        "name": "Wheat",
        "amount": {
          "value": 0.5,
          "unit": "kilograms"
        }
      },
      {
        "name": "Flaked Oats",
        "amount": {
          "value": 0.75,
          "unit": "kilograms"
        }
      },
      {
        "name": "Dark Crystal",
        "amount": {
          "value": 0.75,
          "unit": "kilograms"
        }
      },
      {
        "name": "Carafa Special Malt Type 1",
        "amount": {
          "value": 0.5,
          "unit": "kilograms"
        }
      },
      {
        "name": "Carafa Special Malt Type 3",
        "amount": {
          "value": 0.5,
          "unit": "kilograms"
        }
      },
      {
        "name": "Rye",
        "amount": {
          "value": 0.75,
          "unit": "kilograms"
        }
      },
      {
        "name": "Brown",
        "amount": {
          "value": 0.75,
          "unit": "kilograms"
        }
      }
    ],
    "hops": [
      {
        "name": "Chinook",
        "amount": {
          "value": 25,
          "unit": "grams"
        },
        "add": "start",
        "attribute": "bitter"
      },
      {
        "name": "Sorachi Ace",
        "amount": {
          "value": 50,
          "unit": "grams"
        },
        "add": "start",
        "attribute": "bitter"
      },
      {
        "name": "Ginger Powder",
        "amount": {
          "value": 1.25,
          "unit": "grams"
        },
        "add": "end",
        "attribute": "flavour"
      },
      {
        "name": "Honey",
        "amount": {
          "value": 1250,
          "unit": "grams"
        },
        "add": "end",
        "attribute": "flavour"
      },
      {
        "name": "Cold Infused Coffee",
        "amount": {
          "value": 25,
          "unit": "grams"
        },
        "add": "end",
        "attribute": "flavour"
      }
    ],
    "yeast": "Wyeast 1272 - American Ale II™"
  },
  "food_pairing": [
    "Char sui pork buns",
    "Spicy beef empanadas",
    "Chocolate cheesecake"
  ],
  "brewers_tips": "With stronger styles (like imperial stouts), feel free to cellar your beer and try a bottle every few months to see how the flavours have developed – often the beer picks up new, incredible flavours.",
  "contributed_by": "Sam Mason <samjbmason>"
}
]


.[0]
.[0]."id"
.[0]."name"
.[0]."tagline"
.[0]."first_brewed"
.[0]."description"
.[0]."image_url"
.[0]."abv"
.[0]."ibu"
.[0]."target_fg"
.[0]."target_og"
.[0]."ebc"
.[0]."srm"
.[0]."ph"
.[0]."attenuation_level"
.[0]."volume"
.[0]."volume"."value"
.[0]."volume"."unit"
.[0]."boil_volume"
.[0]."boil_volume"."value"
.[0]."boil_volume"."unit"
.[0]."method"
.[0]."method"."mash_temp"
.[0]."method"."mash_temp"[0]
.[0]."method"."mash_temp"[0]."temp"
.[0]."method"."mash_temp"[0]."temp"."value"
.[0]."method"."mash_temp"[0]."temp"."unit"
.[0]."method"."mash_temp"[0]."duration"
.[0]."method"."fermentation"
.[0]."method"."fermentation"."temp"
.[0]."method"."fermentation"."temp"."value"
.[0]."method"."fermentation"."temp"."unit"
.[0]."method"."twist"
.[0]."ingredients"
.[0]."ingredients"."malt"
.[0]."ingredients"."malt"[0]
.[0]."ingredients"."malt"[0]."name"
.[0]."ingredients"."malt"[0]."amount"
.[0]."ingredients"."malt"[0]."amount"."value"
.[0]."ingredients"."malt"[0]."amount"."unit"
.[0]."ingredients"."malt"[1]
.[0]."ingredients"."malt"[1]."name"
.[0]."ingredients"."malt"[1]."amount"
.[0]."ingredients"."malt"[1]."amount"."value"
.[0]."ingredients"."malt"[1]."amount"."unit"
.[0]."ingredients"."malt"[2]
.[0]."ingredients"."malt"[2]."name"
.[0]."ingredients"."malt"[2]."amount"
.[0]."ingredients"."malt"[2]."amount"."value"
.[0]."ingredients"."malt"[2]."amount"."unit"
.[0]."ingredients"."malt"[3]
.[0]."ingredients"."malt"[3]."name"
.[0]."ingredients"."malt"[3]."amount"
.[0]."ingredients"."malt"[3]."amount"."value"
.[0]."ingredients"."malt"[3]."amount"."unit"
.[0]."ingredients"."malt"[4]
.[0]."ingredients"."malt"[4]."name"
.[0]."ingredients"."malt"[4]."amount"
.[0]."ingredients"."malt"[4]."amount"."value"
.[0]."ingredients"."malt"[4]."amount"."unit"
.[0]."ingredients"."malt"[5]
.[0]."ingredients"."malt"[5]."name"
.[0]."ingredients"."malt"[5]."amount"
.[0]."ingredients"."malt"[5]."amount"."value"
.[0]."ingredients"."malt"[5]."amount"."unit"
.[0]."ingredients"."malt"[6]
.[0]."ingredients"."malt"[6]."name"
.[0]."ingredients"."malt"[6]."amount"
.[0]."ingredients"."malt"[6]."amount"."value"
.[0]."ingredients"."malt"[6]."amount"."unit"
.[0]."ingredients"."malt"[7]
.[0]."ingredients"."malt"[7]."name"
.[0]."ingredients"."malt"[7]."amount"
.[0]."ingredients"."malt"[7]."amount"."value"
.[0]."ingredients"."malt"[7]."amount"."unit"
.[0]."ingredients"."hops"
.[0]."ingredients"."hops"[0]
.[0]."ingredients"."hops"[0]."name"
.[0]."ingredients"."hops"[0]."amount"
.[0]."ingredients"."hops"[0]."amount"."value"
.[0]."ingredients"."hops"[0]."amount"."unit"
.[0]."ingredients"."hops"[0]."add"
.[0]."ingredients"."hops"[0]."attribute"
.[0]."ingredients"."hops"[1]
.[0]."ingredients"."hops"[1]."name"
.[0]."ingredients"."hops"[1]."amount"
.[0]."ingredients"."hops"[1]."amount"."value"
.[0]."ingredients"."hops"[1]."amount"."unit"
.[0]."ingredients"."hops"[1]."add"
.[0]."ingredients"."hops"[1]."attribute"
.[0]."ingredients"."hops"[2]
.[0]."ingredients"."hops"[2]."name"
.[0]."ingredients"."hops"[2]."amount"
.[0]."ingredients"."hops"[2]."amount"."value"
.[0]."ingredients"."hops"[2]."amount"."unit"
.[0]."ingredients"."hops"[2]."add"
.[0]."ingredients"."hops"[2]."attribute"
.[0]."ingredients"."hops"[3]
.[0]."ingredients"."hops"[3]."name"
.[0]."ingredients"."hops"[3]."amount"
.[0]."ingredients"."hops"[3]."amount"."value"
.[0]."ingredients"."hops"[3]."amount"."unit"
.[0]."ingredients"."hops"[3]."add"
.[0]."ingredients"."hops"[3]."attribute"
.[0]."ingredients"."hops"[4]
.[0]."ingredients"."hops"[4]."name"
.[0]."ingredients"."hops"[4]."amount"
.[0]."ingredients"."hops"[4]."amount"."value"
.[0]."ingredients"."hops"[4]."amount"."unit"
.[0]."ingredients"."hops"[4]."add"
.[0]."ingredients"."hops"[4]."attribute"
.[0]."ingredients"."yeast"
.[0]."food_pairing"
.[0]."food_pairing"[0]
.[0]."food_pairing"[1]
.[0]."food_pairing"[2]
.[0]."brewers_tips"
.[0]."contributed_by"

OK

$ cat beer.json 
{
  "id": 222,
  "name": "Dog E",
  "tagline": "Ninth Anniversary Imperial Stout.",
  "first_brewed": "06/2016",
  "description": "Dog E is a very special beer. This beer commemorates our 9th year in 2016. This beer originally appeared as AB:04 in 2010, perhaps the most sought after beer we ever brewed. Dog E is a 16.1% Imperial Stout brewed with copious amounts of dark malts, pure cacao and coffee, balanced by the subtle addition of naga chili, and barrel-aged. Perfect for ageing in your cellar, or drinking fresh if you’re lucky enough to get your paws on a bottle.",
  "image_url": "https://images.punkapi.com/v2/222.png",
  "abv": 16.1,
  "ibu": 100,
  "target_fg": 1125,
  "target_og": 1015,
  "ebc": 500,
  "srm": 254,
  "ph": 4.4,
  "attenuation_level": 84,
  "volume": {
    "value": 20,
    "unit": "liters"
  },
  "boil_volume": {
    "value": 25,
    "unit": "liters"
  },
  "method": {
    "mash_temp": [
      {
        "temp": {
          "value": 63,
          "unit": "celsius"
        },
        "duration": 90
      }
    ],
    "fermentation": {
      "temp": {
        "value": 21,
        "unit": "celsius"
      }
    },
    "twist": "5g Habanero and 3g lemon drop chili in FV"
  },
  "ingredients": {
    "malt": [
      {
        "name": "Pale Ale",
        "amount": {
          "value": 7.5,
          "unit": "kilograms"
        }
      },
      {
        "name": "Wheat",
        "amount": {
          "value": 0.5,
          "unit": "kilograms"
        }
      },
      {
        "name": "Flaked Oats",
        "amount": {
          "value": 0.75,
          "unit": "kilograms"
        }
      },
      {
        "name": "Dark Crystal",
        "amount": {
          "value": 0.75,
          "unit": "kilograms"
        }
      },
      {
        "name": "Carafa Special Malt Type 1",
        "amount": {
          "value": 0.5,
          "unit": "kilograms"
        }
      },
      {
        "name": "Carafa Special Malt Type 3",
        "amount": {
          "value": 0.5,
          "unit": "kilograms"
        }
      },
      {
        "name": "Rye",
        "amount": {
          "value": 0.75,
          "unit": "kilograms"
        }
      },
      {
        "name": "Brown",
        "amount": {
          "value": 0.75,
          "unit": "kilograms"
        }
      }
    ],
    "hops": [
      {
        "name": "Chinook",
        "amount": {
          "value": 25,
          "unit": "grams"
        },
        "add": "start",
        "attribute": "bitter"
      },
      {
        "name": "Sorachi Ace",
        "amount": {
          "value": 50,
          "unit": "grams"
        },
        "add": "start",
        "attribute": "bitter"
      },
      {
        "name": "Ginger Powder",
        "amount": {
          "value": 1.25,
          "unit": "grams"
        },
        "add": "end",
        "attribute": "flavour"
      },
      {
        "name": "Honey",
        "amount": {
          "value": 1250,
          "unit": "grams"
        },
        "add": "end",
        "attribute": "flavour"
      },
      {
        "name": "Cold Infused Coffee",
        "amount": {
          "value": 25,
          "unit": "grams"
        },
        "add": "end",
        "attribute": "flavour"
      }
    ],
    "yeast": "Wyeast 1272 - American Ale II™"
  },
  "food_pairing": [
    "Char sui pork buns",
    "Spicy beef empanadas",
    "Chocolate cheesecake"
  ],
  "brewers_tips": "With stronger styles (like imperial stouts), feel free to cellar your beer and try a bottle every few months to see how the flavours have developed – often the beer picks up new, incredible flavours.",
  "contributed_by": "Sam Mason <samjbmason>"
}

$ cat beer.json | ./jq-paths.sh 

."id"
."name"
."tagline"
."first_brewed"
."description"
."image_url"
."abv"
."ibu"
."target_fg"
."target_og"
."ebc"
."srm"
."ph"
."attenuation_level"
."volume"
."volume"."value"
."volume"."unit"
."boil_volume"
."boil_volume"."value"
."boil_volume"."unit"
."method"
."method"."mash_temp"
."method"."mash_temp"[0]
."method"."mash_temp"[0]."temp"
."method"."mash_temp"[0]."temp"."value"
."method"."mash_temp"[0]."temp"."unit"
."method"."mash_temp"[0]."duration"
."method"."fermentation"
."method"."fermentation"."temp"
."method"."fermentation"."temp"."value"
."method"."fermentation"."temp"."unit"
."method"."twist"
."ingredients"
."ingredients"."malt"
."ingredients"."malt"[0]
."ingredients"."malt"[0]."name"
."ingredients"."malt"[0]."amount"
."ingredients"."malt"[0]."amount"."value"
."ingredients"."malt"[0]."amount"."unit"
."ingredients"."malt"[1]
."ingredients"."malt"[1]."name"
."ingredients"."malt"[1]."amount"
."ingredients"."malt"[1]."amount"."value"
."ingredients"."malt"[1]."amount"."unit"
."ingredients"."malt"[2]
."ingredients"."malt"[2]."name"
."ingredients"."malt"[2]."amount"
."ingredients"."malt"[2]."amount"."value"
."ingredients"."malt"[2]."amount"."unit"
."ingredients"."malt"[3]
."ingredients"."malt"[3]."name"
."ingredients"."malt"[3]."amount"
."ingredients"."malt"[3]."amount"."value"
."ingredients"."malt"[3]."amount"."unit"
."ingredients"."malt"[4]
."ingredients"."malt"[4]."name"
."ingredients"."malt"[4]."amount"
."ingredients"."malt"[4]."amount"."value"
."ingredients"."malt"[4]."amount"."unit"
."ingredients"."malt"[5]
."ingredients"."malt"[5]."name"
."ingredients"."malt"[5]."amount"
."ingredients"."malt"[5]."amount"."value"
."ingredients"."malt"[5]."amount"."unit"
."ingredients"."malt"[6]
."ingredients"."malt"[6]."name"
."ingredients"."malt"[6]."amount"
."ingredients"."malt"[6]."amount"."value"
."ingredients"."malt"[6]."amount"."unit"
."ingredients"."malt"[7]
."ingredients"."malt"[7]."name"
."ingredients"."malt"[7]."amount"
."ingredients"."malt"[7]."amount"."value"
."ingredients"."malt"[7]."amount"."unit"
."ingredients"."hops"
."ingredients"."hops"[0]
."ingredients"."hops"[0]."name"
."ingredients"."hops"[0]."amount"
."ingredients"."hops"[0]."amount"."value"
."ingredients"."hops"[0]."amount"."unit"
."ingredients"."hops"[0]."add"
."ingredients"."hops"[0]."attribute"
."ingredients"."hops"[1]
."ingredients"."hops"[1]."name"
."ingredients"."hops"[1]."amount"
."ingredients"."hops"[1]."amount"."value"
."ingredients"."hops"[1]."amount"."unit"
."ingredients"."hops"[1]."add"
."ingredients"."hops"[1]."attribute"
."ingredients"."hops"[2]
."ingredients"."hops"[2]."name"
."ingredients"."hops"[2]."amount"
."ingredients"."hops"[2]."amount"."value"
."ingredients"."hops"[2]."amount"."unit"
."ingredients"."hops"[2]."add"
."ingredients"."hops"[2]."attribute"
."ingredients"."hops"[3]
."ingredients"."hops"[3]."name"
."ingredients"."hops"[3]."amount"
."ingredients"."hops"[3]."amount"."value"
."ingredients"."hops"[3]."amount"."unit"
."ingredients"."hops"[3]."add"
."ingredients"."hops"[3]."attribute"
."ingredients"."hops"[4]
."ingredients"."hops"[4]."name"
."ingredients"."hops"[4]."amount"
."ingredients"."hops"[4]."amount"."value"
."ingredients"."hops"[4]."amount"."unit"
."ingredients"."hops"[4]."add"
."ingredients"."hops"[4]."attribute"
."ingredients"."yeast"
."food_pairing"
."food_pairing"[0]
."food_pairing"[1]
."food_pairing"[2]
."brewers_tips"
."contributed_by"

OK

Links

Further reading

Where to go next

Last page was exercises for introduction to Json. The next page will be exercises for jq if any.

The TOC goes to Java_Web_programming.

« PreviousBook TOCNext »