Skip to content

Instantly share code, notes, and snippets.

@wxgeorge
Created January 10, 2020 21:50
Show Gist options
  • Save wxgeorge/75e6684af0fcd42580cbb693384a9d96 to your computer and use it in GitHub Desktop.
Save wxgeorge/75e6684af0fcd42580cbb693384a9d96 to your computer and use it in GitHub Desktop.
Yukon Tech Collective January 2020 meetup notes

We investigated the tool jq.

Wes first encountered this as a query tool for JSON. Our probing with the tool lead us to believe that it is much more than this.

This author intends to investigate JSONPath in the future, as it feels targetted specifically at querying. jq is capable of arbitrary JSON transformations. There is also JMESpath which is described as query language for JSON (this author was under the impression JMESpath was also capable of JSON transformations, albeit a more limited set than jq allows for the expression of)

First we needed some JSON. @ryanagar noted the considerable breadth of Yukon GIS data. With the help of a query builder, we were able to pull down a blob, and the task for the group was to investigate it's structure with jq, thereby probing jq's expressiveness.

URL='http://mapservices.gov.yk.ca/arcgis/rest/services/GeoYukon/GY_Transportation/MapServer/4/query?where=1%3D1&text=&objectIds=&time=&geometry=&geometryType=esriGeometryEnvelope&inSR=&spatialRel=esriSpatialRelIntersects&relationParam=&outFields=*&returnGeometry=true&returnTrueCurves=false&maxAllowableOffset=&geometryPrecision=&outSR=&having=&returnIdsOnly=false&returnCountOnly=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&gdbVersion=&historicMoment=&returnDistinctValues=false&resultOffset=&resultRecordCount=&queryByDistance=&returnExtentOnly=false&datumTransformation=&parameterValues=&rangeValues=&quantizationParameters=&f=pjson'
curl ${URL} > yg_gis.json

What we got was a complex object, the structure of which we wanted to understand.

cat yg_gis.json | jq '. | keys'
[
  "displayFieldName",
  "features",
  "fieldAliases",
  "fields",
  "geometryType",
  "spatialReference"
]

The goal was to use jq to tell us the structure of the object, by reporting the types of each members. Our goal was the following output:

[
  ["displayFieldName", "string"],
  ["features", "array"],
  ["fieldAliases", "object"],
  ["fields", "array"],
  ["geometryType", "string"],
  ["spatialReference", "object"]
]

(i.e. we've identified the type of each object member. Note that cat yg_gis.json | jq '.displayFieldName | type' returns string)

What follows is our collective exploration, mostly mobbed with @anlek reading docs and the broader group hurling suggestions pop-corn style :)

Our eventual solution returned

{
  "displayFieldName": "string"
}
{
  "features": "array"
}
{
  "fieldAliases": "object"
}
{
  "fields": "array"
}
{
  "geometryType": "string"
}
{
  "spatialReference": "object"
}

which isn't quite what we were were after, but close enough ;)

cat yg_gis.json | jq '. as $source | keys[] | . as $key | $source[.] | {($key): type}'

cat yg_gis.json | jq '.[] | .. | {(values): type} '

cat yg_gis.json | jq '. | type'
cat yg_gis.json | jq '. | keys'
cat yg_gis.json | jq '.displayFieldName | type'
cat yg_gis.json | jq '.displayFieldName'
cat yg_gis.json | jq '.features | type'
cat yg_gis.json | jq '.fieldAliases | type'
cat yg_gis.json | jq '.fields | type'
cat yg_gis.json | jq '.geometryType | type'
cat yg_gis.json | jq '.geometryTyp'
cat yg_gis.json | jq '.geometryType'
cat yg_gis.json | jq '.spatialReference | type'
cat yg_gis.json | jq '.' | wc -l
cat yg_gis.json | jq '. | keys'
cat yg_gis.json | jq '. | keys'
cat yg_gis.json | jq '.displayFieldName | array'
cat yg_gis.json | jq '.displayFieldName | type'
cat yg_gis.json | jq '. | keys'
cat yg_gis.json | jq '. | keys | type'
cat yg_gis.json | jq '. | keys | .[] | type'
cat yg_gis.json | jq '{key: .key}'
URL='http://mapservices.gov.yk.ca/arcgis/rest/services/GeoYukon/GY_Transportation/MapServer/4/query?where=1%3D1&text=&objectIds=&time=&geometry=&geometryType=esriGeometryEnvelope&inSR=&spatialRel=esriSpatialRelIntersects&relationParam=&outFields=*&returnGeometry=true&returnTrueCurves=false&maxAllowableOffset=&geometryPrecision=&outSR=&having=&returnIdsOnly=false&returnCountOnly=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&gdbVersion=&historicMoment=&returnDistinctValues=false&resultOffset=&resultRecordCount=&queryByDistance=&returnExtentOnly=false&datumTransformation=&parameterValues=&rangeValues=&quantizationParameters=&f=pjson'
curl ${URL} | tee yg_gis.json | jq '.'
cat yg_gis.json | jq '{key: .keys}'
cat yg_gis.json | jq '. | keys'
cat yg_gis.json | jq '[0,1,2] | keys'
cat yg_gis.json | jq '[0,1,2] | type'
cat yg_gis.json | jq '. | keys'
cat yg_gis.json | jq '. | values | '
cat yg_gis.json | jq '. | values'
cat yg_gis.json | jq '. | values'
cat yg_gis.json | jq '. | values | type'
cat yg_gis.json | jq '. | values | keys'
cat yg_gis.json | jq '. | keys'
cat yg_gis.json | jq '. | type'
cat yg_gis.json | jq '.'
cat yg_gis.json | jq '.. | values'
cat yg_gis.json | jq '..'
cat yg_gis.json | jq '...'
cat yg_gis.json | jq '.*'
cat yg_gis.json | jq '..'
cat yg_gis.json | jq '.. | type'
cat yg_gis.json | jq '[..] | length'
cat yg_gis.json | jq '. | .'
cat yg_gis.json | jq '. | . | keys'
cat yg_gis.json | jq '. | keys'
cat yg_gis.json | jq '. | keys'
cat yg_gis.json | jq '. | keys | {(.)}'
cat yg_gis.json | jq '. | keys | {(.): true}'
cat yg_gis.json | jq '. | keys | {.: true}'
cat yg_gis.json | jq '. | keys | {(.): true}'
cat yg_gis.json | jq '. {(.): true}'
cat yg_gis.json | jq '. | {(.): true}'
cat yg_gis.json | jq '. | {(.): true}'
cat yg_gis.json | jq '. | {(keys): true}'
cat yg_gis.json | jq '. | {(keys): type}'
cat yg_gis.json | jq '.. | [keys, type]'
cat yg_gis.json | jq '. | [keys, type]'
cat yg_gis.json | jq '. | [[keys | keys, type]]'
cat yg_gis.json | jq '. | [[keys | values, type]]'
cat yg_gis.json | jq '. | keys | values, type'
cat yg_gis.json | jq '. | keys | .., type'
cat yg_gis.json | jq '. | keys | .., type'
cat yg_gis.json | jq ' recurse(.) | type'
cat yg_gis.json | jq ' recurse(.) |[ keys, type]'
cat yg_gis.json | jq ' recurse(.) |[.keys,.type]'
cat yg_gis.json | jq ' recurse(.)'
cat yg_gis.json | jq ' .'
cat yg_gis.json | jq '. | (keys, type)'
cat yg_gis.json | jq 'type'
cat yg_gis.json | jq 'type .'
cat yg_gis.json | jq '.. type'
cat yg_gis.json | jq '.. | type'
cat yg_gis.json | jq '. | keys, (.. | type)'
cat yg_gis.json | jq '. | [keys, (.. | type)]'
cat yg_gis.json | jq '. | [keys, (. | type)]'
cat yg_gis.json | jq '. | [keys, . | type]'
cat yg_gis.json | jq '.[]'
cat yg_gis.json | jq '.[][]'
cat yg_gis.json | jq '.[].'
cat yg_gis.json | jq '.[] | objects'
cat yg_gis.json | jq '.[] | objects, type'
cat yg_gis.json | jq '.[] | keys, type'
cat yg_gis.json | jq '.[] | keys'
cat yg_gis.json | jq '.[] keys'
cat yg_gis.json | jq '. | keys'
cat yg_gis.json | jq '(. | keys), (. | keys)'
cat yg_gis.json | jq '(. | keys, . | keys)'
cat yg_gis.json | jq '([. | keys], [. | keys]) | keys'
cat yg_gis.json | jq '.[*]'
cat yg_gis.json | jq '.[]'
cat yg_gis.json | jq '[1,2,3]..'
cat yg_gis.json | jq '[1,2,3] | map'
cat yg_gis.json | jq '[1,2,3] | math'
cat yg_gis.json | jq '[1,2,3] | map(type)'
cat yg_gis.json | jq '[1,2,3] | map(keys, type)'
cat yg_gis.json | jq '[1,2,3] | keys'
cat yg_gis.json | jq '[1,2,3] | type'
cat yg_gis.json | jq '[1,2,3]. | type'
cat yg_gis.json | jq '[1,2,3][] | type'
cat yg_gis.json | jq '[1,2,3][.] | type'
cat yg_gis.json | jq '[1,2,3][] | [type]'
cat yg_gis.json | jq '[[1,2,3][] | type]'
cat yg_gis.json | jq '[[1,2,3] | values | type]'
cat yg_gis.json | jq '[[1,2,3] | . | type]'
cat yg_gis.json | jq '[[1,2,3] | .. | type]'
cat yg_gis.json | jq '[[1,2,3] | type]'
cat yg_gis.json | jq '[[1,2,3]. | type]'
cat yg_gis.json | jq '[[1,2,3] | .]'
cat yg_gis.json | jq '[[1,2,3] | values]'
cat yg_gis.json | jq '[4,5,6] | types'
cat yg_gis.json | jq '[4,5,6][] | types'
cat yg_gis.json | jq '[4,5,6][] | type'
cat yg_gis.json | jq '[4,5,6][] | type'
cat yg_gis.json | jq '[4,5,6][] | keys'
cat yg_gis.json | jq '[4,5,6][]'
cat yg_gis.json | jq '[4,5,6][] | {., type}'
cat yg_gis.json | jq '[4,5,6][] | {.: type}'
cat yg_gis.json | jq '[4,5,6][] | {(.): type}'
cat yg_gis.json | jq '[4,5,6][] | [(.), type]'
cat yg_gis.json | jq '[4,5,6][] | {key:values'
cat yg_gis.json | jq '[4,5,6][] | {type: values'
cat yg_gis.json | jq '[4,5,6][] | {type: values}'
cat yg_gis.json | jq '[4,5,6][] | {(type): values}'
cat yg_gis.json | jq '.[] | {(type): values}'
cat yg_gis.json | jq '..[] | {(type): values}'
cat yg_gis.json | jq '.[][] | {(type): values}'
cat yg_gis.json | jq '.[] | {(type): values}'
cat yg_gis.json | jq '. | {(type): values}'
cat yg_gis.json | jq '.. | {(type): values}'
cat yg_gis.json | jq '.. | keys, . | {(type): values}'
cat yg_gis.json | jq '.[] | keys, . | {(type): values}'
cat yg_gis.json | jq '. | keys, . | {(type): values}'
cat yg_gis.json | jq '. | (keys, .) | {(type): values}'
cat yg_gis.json | jq '. | (keys, .)'
cat yg_gis.json | jq '. | (keys, .)'
cat yg_gis.json | jq '. | keys'
cat yg_gis.json | jq '. | keys, (. | type)'
cat yg_gis.json | jq '. | keys, (values | type)'
cat yg_gis.json | jq '. | (keys . | type)'
cat yg_gis.json | jq '. | (keys, . | type)'
cat yg_gis.json | jq '. | {(type), .}'
cat yg_gis.json | jq '. | keys | .[]'
cat yg_gis.json | jq '. | (keys | .[]), type'
cat yg_gis.json | jq '. | (keys | .[]), [] | type'
cat yg_gis.json | jq '. | {(type): values}'
cat yg_gis.json | jq '.. | {(type): values}'
cat yg_gis.json | jq '.. | {(.): type}'
cat yg_gis.json | jq '.. | {('test'): type}'
cat yg_gis.json | jq '.. | {test: type}'
cat yg_gis.json | jq '.. | {(): type}'
cat yg_gis.json | jq '.. | {(keys | []): type}'
cat yg_gis.json | jq '.. | {(keys[]): type}'
cat yg_gis.json | jq '. | {(keys[]): type}'
cat yg_gis.json | jq '. | {([].keys[]): type}'
cat yg_gis.json | jq '. | {([] | keys[]): type}'
cat yg_gis.json | jq '. | {(keys[]): type}'
cat yg_gis.json | jq '. | {(keys[]), type}'
cat yg_gis.json | jq '. | {(keys[]): type}'
cat yg_gis.json | jq '. | {(keys[]): (.. | type)}'
cat yg_gis.json | jq '. | {(keys[]): (.[] | type)}'
cat yg_gis.json | jq '. | {(keys[]): (.[] | keys | type)}'
cat yg_gis.json | jq '. | {(keys[]): (. | keys | type)}'
cat yg_gis.json | jq '. | {(keys): (. | keys | type)}'
cat yg_gis.json | jq '. | {(keys[]): (. | keys)}'
cat yg_gis.json | jq '. | {(keys): (.. | type)}'
cat yg_gis.json | jq '. | {(keys): (.[] | type)}'
cat yg_gis.json | jq '. | {(keys): (key[] | type)}'
cat yg_gis.json | jq '. | {(keys): (keys[] | type)}'
cat yg_gis.json | jq '. | {(keys[]): (keys[] | type)}'
cat yg_gis.json | jq '. | {(keys[]): (keys[])}'
cat yg_gis.json | jq '. | {(keys[]): ([])}'
cat yg_gis.json | jq '. | {(keys[]): (.[])}'
cat yg_gis.json | jq '. | {(keys[]): (keys[])}'
cat yg_gis.json | jq '. | {(keys[]): (.[keys[]])}'
cat yg_gis.json | jq '. | {(keys[]): (.(keys[]))}'
cat yg_gis.json | jq '. | {(keys[]): (.[keys[])]}'
cat yg_gis.json | jq '. | {(keys[]): ([values[])}'
cat yg_gis.json | jq '. | {(keys[]): (values[])}'
cat yg_gis.json | jq '. | {(keys[]): (.)}'
cat yg_gis.json | jq '. | {(keys[]): (..)}'
cat yg_gis.json | jq '. | {(keys[]): (.. | type)}'
cat yg_gis.json | jq '. | {(keys[]): (.(keys[]))}'
cat yg_gis.json | jq '. | {(keys[]): (.. | type)}'
cat yg_gis.json | jq '. | {(..): (.. | type)}'
cat yg_gis.json | jq '. | {(.. | keys): (.. | type)}'
cat yg_gis.json | jq '. | {(. | keys): (.. | type)}'
cat yg_gis.json | jq '. | {([] | keys): (.. | type)}'
cat yg_gis.json | jq '. | {(keys): (.. | type)}'
cat yg_gis.json | jq '. | {(keys[]): (.. | type)}'
cat yg_gis.json | jq '.'
cat yg_gis.json | jq '.' | keys
cat yg_gis.json | jq '.' | {key: keys}
cat yg_gis.json | jq '. | (keys[]): (.. | type)'
cat yg_gis.json | jq '. | (keys[]), (.. | type)'
cat yg_gis.json | jq '.. | (keys[]), (.. | type)'
cat yg_gis.json | jq '. | (keys[])'
cat yg_gis.json | jq '. | (keys[])'
cat yg_gis.json | jq '.. | keys'
cat yg_gis.json | jq '.[] | keys'
cat yg_gis.json | jq '. | keys[]'
cat yg_gis.json | jq '.[]'
cat yg_gis.json | jq '.[][]'
cat yg_gis.json | jq '.[] | keys'
cat yg_gis.json | jq '.[][0]'
cat yg_gis.json | jq '.[0]'
cat yg_gis.json | jq '.[]'
cat yg_gis.json | jq '.[] | values'
cat yg_gis.json | jq '.[].0'
cat yg_gis.json | jq '.0'
cat yg_gis.json | jq '.'
cat yg_gis.json | jq '.[]' 
cat yg_gis.json | jq '. | recurse(keys)' 
cat yg_gis.json | jq '. | keys[] | recurse(.)' 
cat yg_gis.json | jq '. | keys[] ' 
cat yg_gis.json | jq '. | keys ' 
cat yg_gis.json | jq '.[] | keys ' 
cat yg_gis.json | jq '.' 
cat yg_gis.json | jq '.[]' 
cat yg_gis.json | jq '. | (keys[]): (.. | type)'
cat yg_gis.json | jq '. as $source | keys[] | $source(.)'
cat yg_gis.json | jq '. as $source | keys[] | $source(.)'
cat yg_gis.json | jq '. as $source | keys[] | $source'
cat yg_gis.json | jq '. as $source | keys[] | $source.(.)'
cat yg_gis.json | jq '. as $source | keys[] | $source[.]'
cat yg_gis.json | jq '. as $source | keys[] | $source[.] | type'
cat yg_gis.json | jq '. as $source | keys[] as $key | $source[.] | {($key) : type}'
cat yg_gis.json | jq '. as $source | keys[] as $key | $source[.] | {($key): type}'
cat yg_gis.json | jq '. as $source | keys[] as $key | $source[.] | {($key[]): type}'
cat yg_gis.json | jq '. as $source | keys[] | . as $key | $source[.] | {($key): type}'
cat yg_gis.json | jq '. as $source | keys[] | . as $key | $source[.] | ($key), type'
cat yg_gis.json | jq '. as $source | keys[] | . as $key | $source[.] | {($key): type}'
cat yg_gis.json | jq '[4,5,6][] | {(type): values}'
cat yg_gis.json | jq '. as $source | keys[] | . as $key | $source[.] | {($key): type}' 
cat yg_gis.json | jq '[{number: 4},{number:5},{number: 6}][] | {(type): values}'
cat yg_gis.json | jq '[{number: 4},{number:5},{number: 6}] | {(type): values}'
cat yg_gis.json | jq '[{value: 4},{value:5},{value: 6}] | {(type): values}'
cat yg_gis.json | jq '[{value: 4},{value:5},{value: 6}][] | {(type): values}'
cat yg_gis.json | jq '[{value: 4},{value:5},{value: 6}][] | .. | {(type): values}'
cat yg_gis.json | jq '[{value: 4},{value:5},{value: 6}][][] | .. | {(type): values}'
cat yg_gis.json | jq '[{value: 4, test: 6},{value:5},{value: 6}][][] | .. | {(type): values}'
cat yg_gis.json | jq '[{value: 4, test: 6},{value:5},{value: 6}][][] |{test:  .. | {(type): values}} '
cat yg_gis.json | jq '[{value: 4, test: 6},{value:5},{value: 6}][][] |  .. | {(type): values} '
cat yg_gis.json | jq '[{value: 4, test: 6},{value:5,test: 7},{value: 6}][][] |  .. | {(type): values} '
cat yg_gis.json | jq '[{value: 4, test: 6},{value:5,test: 7},{value: 6}][][] | [ .. | {(type): values}]'
cat yg_gis.json | jq '[[{value: 4, test: 6},{value:5,test: 7},{value: 6}][][] |  .. | {(type): values}]'
cat yg_gis.json | jq '.[][] |  .. | {(type): values}] '
cat yg_gis.json | jq '.[] |  .. | {(type): values}] '
jq '[1,2,3] |=.'
jq '[1,2,3] |=.+1'
jq '[1,2,3] |=. + 1'
jq '[1,2,3] |= . + 1'
jq '[1,2,3] |= (. + 1)'
cat yg_gis.json | jq '[[{value: 4, test: 6},{value:5,test: 7},{value: 6}][][] |  .. | {(type): values}]'
cat yg_gis.json | jq '.[][] |  .. | {(type): values}] '
cat yg_gis.json | jq '.[] |  .. | {(type): values}] '
cat yg_gis.json | jq '.[] | .. | {(type): values} '
cat yg_gis.json | jq '.[] | .. | {(values): type} '
cat yg_gis.json | jq '.[] | .. | {(values): type} '
cat yg_gis.json | jq '. | {(.):type}'
cat yg_gis.json | jq '. | {(.|keys):type}'
cat yg_gis.json | jq '. | {(.| keys[]):type}'
cat yg_gis.json | jq '. | {(.| keys[]):(. | keys[] | type)}'
cat yg_gis.json | jq '. | {(.| keys[]):(.[] | type)}'
cat yg_gis.json | jq '. | {(.[]| keys[]):(.[] | type)}'
cat yg_gis.json | jq '. | {(.[]):(.[] | type)}'
cat yg_gis.json | jq '. | {(.[]):(.[] | type)}'
@anlek
Copy link

anlek commented Jan 10, 2020

I think we'd get the result we want if we ran cat yg_gis.json | jq '. as $source | keys[] | . as $key | $source[.] | [[$key, type]]'. The change being [[$key, type]] vs {($key): type}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment