Package: qic
doc on github.ioqic - Query In ConsoleJSON/YAML/XML comand line query tool with interactive mode.By design, it tries to keep simple. There're a lot compromises. It's not intending to embed a full syntax/sementic engine. For complicated situation, other than introducing very long single line expression, please try code blocks where you can use any python syntax.This document is available with better format on github.ioQiCwhere colorful text can be used for terminal output.InstallationBasicsCheck expanded codeKeys with special charsInteractive modeValidate/Convert JSON/YAML/XMLLimit rowsLoad extra modulesJSON/YAML/XML to HTMLInstallationpython -mpip install qicrun itqicorpython -mqicBasicsby default it will validate, reformat and color the JSON stream."_" means the document root.  This is the default value.(py3) [me@mtp qic]$ cat test/s1.json | qic  # _
[
  {"_id": {"$oid": "5968dd23fc13ae04d9000001"
    },"product_name": "sildenafil citrate","supplier": "Wisozk Inc","quantity": 261,"unit_cost": "$10.47"
  },
  {"_id": {"$oid": "5968dd23fc13ae04d9000002"
    },"product_name": "Mountain Juniperus ashei","supplier": "Keebler-Hilpert","quantity": 292,"unit_cost": "$8.74"
  },
  {"_id": {"$oid": "5968dd23fc13ae04d9000003"
    },"product_name": "Dextromathorphan HBr","supplier": "Schmitt-Weissnat","quantity": 211,"unit_cost": "$20.53"
  }
]query its conent,(py3) [me@mtp qic]$ cat test/s1.json | qic  "_[0]"
{"_id": {"$oid": "5968dd23fc13ae04d9000001"
  },"product_name": "sildenafil citrate","supplier": "Wisozk Inc","quantity": 261,"unit_cost": "$10.47"
}

(py3) [me@mtp qic]$ 
(py3) [me@mtp qic]$ cat test/s1.json | qic  "_[0]._id"
{"$oid": "5968dd23fc13ae04d9000001"
}

(py3) [me@mtp qic]$ 
(py3) [me@mtp qic]$ cat test/s1.json | qic  "_[0].product_name"
sildenafil citrate

(py3) [me@mtp qic]$ 
(py3) [me@mtp qic]$ cat test/s1.json | qic  "_[0].{product_name, quantity, unit_cost}"
{"product_name": "sildenafil citrate","quantity": 261,"unit_cost": "$10.47"
}

(py3) [me@mtp qic]$ 
(py3) [me@mtp qic]$ cat test/s1.json | qic  "_[]._id"
[
  {"$oid": "5968dd23fc13ae04d9000001"
  },
  {"$oid": "5968dd23fc13ae04d9000002"
  },
  {"$oid": "5968dd23fc13ae04d9000003"
  }
]

(py3) [me@mtp qic]$ 
(py3) [me@mtp qic]$ cat test/s1.json | qic  "_[].{_id,quantity}"
[
  {"_id": {"$oid": "5968dd23fc13ae04d9000001"
    },"quantity": 261
  },
  {"_id": {"$oid": "5968dd23fc13ae04d9000002"
    },"quantity": 292
  },
  {"_id": {"$oid": "5968dd23fc13ae04d9000003"
    },"quantity": 211
  }
]Check expanded code(py3) [me@mtp qic]$ cat test/s1.json | qic  "_[]._id" -X
# run : 
[ _umy['_id'] for _umy in _ ]
[
  {"$oid": "5968dd23fc13ae04d9000001"
  },
  {"$oid": "5968dd23fc13ae04d9000002"
  },
  {"$oid": "5968dd23fc13ae04d9000003"
  }
]

(py3) [me@mtp qic]$ cat test/s1.json | qic  "[ _[0].product_name ]" -X
# run : 
[ _[0]['product_name'] ]
[
  "sildenafil citrate"
]

(py3) [me@mtp qic]$ 
(py3) [me@mtp qic]$ cat test/s1.json | qic  "_[].{_id,quantity}" -X
# run : 
[ {'_id':_emt['_id'],'quantity':_emt['quantity']} for _emt in _ ]
[
  {"_id": {"$oid": "5968dd23fc13ae04d9000001"
    },"quantity": 261
  },
  {"_id": {"$oid": "5968dd23fc13ae04d9000002"
    },"quantity": 292
  },
  {"_id": {"$oid": "5968dd23fc13ae04d9000003"
    },"quantity": 211
  }
]


(py3) [me@mtp qic]$ cat test/s1.json | qic  "_[0].{_id,quantity}" -X
# run : 
{'_id':_[0]['_id'],'quantity':_[0]['quantity']}
{"_id": {"$oid": "5968dd23fc13ae04d9000001"
  },"quantity": 261
}Keys with special charslook at below changed JSON,product_nameis renamed toproduct.name. This will break the dot expansion QiC is using. In this situation, use<>to mark content within is a single unit.(py3) [me@mtp qic]$ qic -f test/s1x.json 
[
  {"_id": {"$oid": "5968dd23fc13ae04d9000001"
    },"product.name": "sildenafil citrate","supplier": "Wisozk Inc","quantity": 261,"unit_cost": "$10.47"
  },
  {"_id": {"$oid": "5968dd23fc13ae04d9000002"
    },"product.name": "Mountain Juniperus ashei","supplier": "Keebler-Hilpert","quantity": 292,"unit_cost": "$8.74"
  },
  {"_id": {"$oid": "5968dd23fc13ae04d9000003"
    },"product.name": "Dextromathorphan HBr","supplier": "Schmitt-Weissnat","quantity": 211,"unit_cost": "$20.53"
  }
]

(py3) [me@mtp qic]$ 
(py3) [me@mtp qic]$ qic -f test/s1x.json  "_[].product.name"
# expanded code :
[ _kom['product']['name'] for _kom in _ ]
# KeyError: 'product'
(py3) [me@mtp qic]$ 
(py3) [me@mtp qic]$ qic -f test/s1x.json  "_[].<product.name>"
[
  "sildenafil citrate",
  "Mountain Juniperus ashei",
  "Dextromathorphan HBr"
]Interactive Mode-Ienable interactive mode.Qic will read user input from sys.stdin.  so, for input stream, it could not be from unix pipe, instead use-fopiton.when type_, a small menu is promptec all internal functions started with_.Before prompted for user input, all keys in the JSON are stored for word completion prompt -- as you may have noticed, they're case insenstive.(py3) [me@mtp qic]$ qic -f test/s6.json  -I
[qic] $ ___fl_flatlist_j_l_l2pt_l2t[qic] $ _.users[0].ffirstname[qic] $ _.users[0].firstname
Krish_l2t is an internal function which print "standard" table.   \[qic] $ _l2t(_.users)userId firstName lastName phoneNumber emailAddress------------------------------------------------------------------------
1      Krish     Lee      123456      krish.lee@learningcontainer.com
2      racks     jacson   123456      racks.jacson@learningcontainer.com
3      denial    roast    33333333    denial.roast@learningcontainer.com
4      devid     neo      222222222   devid.neo@learningcontainer.com
5      jone      mac      111111111   jone.mac@learningcontainer.comuse'''to mark code block start and end.[qic] $
[qic] $ '''
[qic] $ guys = ""
[qic] $foriin_.users :
[qic] $     guys += i.firstname + i.lastname + ", "
[qic] $ print("List :", guys.rstrip())
[qic] $
[qic] $ '''
List : KrishLee, racksjacson, denialroast, devidneo, jonemac,
[qic] $
[qic] $use\qorquit()to leave Qic.(py3) [me@mtp qic]$ 
(py3) [me@mtp qic]$ qic -f test/s6.json  -I
[qic] $
[qic] $ \q
(py3) [me@mtp qic]$ 
(py3) [me@mtp qic]$ qic -f test/s6.json  -I
[qic] $ quit()
(py3) [me@mtp qic]$Validate and Convert JSON/XML/YAMLwithout any parameters, feed input into QiC and it will serve as a format validator ( plus foramatter, etc.).-tspecify source as JSON, YAML or XML. here all examples are from JSON format andJSONis the default type.  Choose the right one if you're going to working with YAML or XML.Internal function_jsonor-jwill dump output as well formatted JSON and this is the default behaviour._yamlor_ywill dump well formatted YAML, while_xmlor_xwill dump well formatted XML.specify them in format of_x($expr), if for full doc, say,_x(_), just use_x.(py3) [me@mtp qic]$ qic -f test/s6.json  _x
<?xml version="1.0" ?><root><userstype="list"><itemtype="dict"><userIdtype="int">1</userId><firstNametype="str">Krish</firstName><lastNametype="str">Lee</lastName><phoneNumbertype="str">123456</phoneNumber><emailAddresstype="str">krish.lee@learningcontainer.com</emailAddress></item><itemtype="dict"><userIdtype="int">2</userId><firstNametype="str">racks</firstName><lastNametype="str">jacson</lastName><phoneNumbertype="str">123456</phoneNumber><emailAddresstype="str">racks.jacson@learningcontainer.com</emailAddress></item><itemtype="dict"><userIdtype="int">3</userId><firstNametype="str">denial</firstName><lastNametype="str">roast</lastName><phoneNumbertype="str">33333333</phoneNumber><emailAddresstype="str">denial.roast@learningcontainer.com</emailAddress></item><itemtype="dict"><userIdtype="int">4</userId><firstNametype="str">devid</firstName><lastNametype="str">neo</lastName><phoneNumbertype="str">222222222</phoneNumber><emailAddresstype="str">devid.neo@learningcontainer.com</emailAddress></item><itemtype="dict"><userIdtype="int">5</userId><firstNametype="str">jone</firstName><lastNametype="str">mac</lastName><phoneNumbertype="str">111111111</phoneNumber><emailAddresstype="str">jone.mac@learningcontainer.com</emailAddress></item></users></root>(py3) [me@mtp qic]$ 
(py3) [me@mtp qic]$ qic -f test/s6.json  _y---users:
-emailAddress: krish.lee@learningcontainer.comfirstName: KrishlastName: LeephoneNumber: '123456'userId: 1
-emailAddress: racks.jacson@learningcontainer.comfirstName: rackslastName: jacsonphoneNumber: '123456'userId: 2
-emailAddress: denial.roast@learningcontainer.comfirstName: deniallastName: roastphoneNumber: '33333333'userId: 3
-emailAddress: devid.neo@learningcontainer.comfirstName: devidlastName: neophoneNumber: '222222222'userId: 4
-emailAddress: jone.mac@learningcontainer.comfirstName: jonelastName: macphoneNumber: '111111111'userId: 5

(py3) [me@mtp qic]$ 
(py3) [me@mtp qic]$ qic -f test/s6.json  '_y(_)'---users:
-emailAddress: krish.lee@learningcontainer.comfirstName: KrishlastName: LeephoneNumber: '123456'userId: 1
-emailAddress: racks.jacson@learningcontainer.comfirstName: rackslastName: jacsonphoneNumber: '123456'userId: 2
-emailAddress: denial.roast@learningcontainer.comfirstName: deniallastName: roastphoneNumber: '33333333'userId: 3
-emailAddress: devid.neo@learningcontainer.comfirstName: devidlastName: neophoneNumber: '222222222'userId: 4
-emailAddress: jone.mac@learningcontainer.comfirstName: jonelastName: macphoneNumber: '111111111'userId: 5

(py3) [me@mtp qic]$ 
(py3) [me@mtp qic]$ qic -f test/s6.json  '_y(_.users[:2])'----emailAddress: krish.lee@learningcontainer.comfirstName: KrishlastName: LeephoneNumber: '123456'userId: 1
-emailAddress: racks.jacson@learningcontainer.comfirstName: rackslastName: jacsonphoneNumber: '123456'userId: 2

(py3) [me@mtp qic]$Limit rowswhen the embeded list is huge, we may only want to see a few of them.slice[:$n]can be used for specified list, but-l $napply to all lists included.(py3) [me@mtp qic]$ qic -f test/s6.json '_.users' | qic _y----emailAddress: krish.lee@learningcontainer.comfirstName: KrishlastName: LeephoneNumber: '123456'userId: 1
-emailAddress: racks.jacson@learningcontainer.comfirstName: rackslastName: jacsonphoneNumber: '123456'userId: 2
-emailAddress: denial.roast@learningcontainer.comfirstName: deniallastName: roastphoneNumber: '33333333'userId: 3
-emailAddress: devid.neo@learningcontainer.comfirstName: devidlastName: neophoneNumber: '222222222'userId: 4
-emailAddress: jone.mac@learningcontainer.comfirstName: jonelastName: macphoneNumber: '111111111'userId: 5

(py3) [me@mtp qic]$ qic -f test/s6.json -l2 '_.users' | qic _y
# _[] 5 -> 2----emailAddress: krish.lee@learningcontainer.comfirstName: KrishlastName: LeephoneNumber: '123456'userId: 1
-emailAddress: racks.jacson@learningcontainer.comfirstName: rackslastName: jacsonphoneNumber: '123456'userId: 2

(py3) [me@mtp qic]$ qic -f test/s6.json -l2 '_.users[:2]' 
[
  {"userId": 1,"firstName": "Krish","lastName": "Lee","phoneNumber": "123456","emailAddress": "krish.lee@learningcontainer.com"
  },
  {"userId": 2,"firstName": "racks","lastName": "jacson","phoneNumber": "123456","emailAddress": "racks.jacson@learningcontainer.com"
  }
]load extra modulesload module/class/function from python source files.yonghang@mtp~ $ cat ~/tmp/tm.py 

def xxlen(ds) :
    return str(len(ds)) + " : " + str(ds)

yonghang@mtp~ $ curl -s walkerever.com/share/test/json/s6.json | qic -m ~/tmp/tm.py "tm.xxlen(_)"
1 : {'users': [{'userId': 1, 'firstName': 'Krish', 'lastName': 'Lee', 'phoneNumber': '123456', 'emailAddress': 'krish.lee@learningcontainer.com'}, {'userId': 2, 'firstName': 'racks', 'lastName': 'jacson', 'phoneNumber': '123456', 'emailAddress': 'racks.jacson@learningcontainer.com'}, {'userId': 3, 'firstName': 'denial', 'lastName': 'roast', 'phoneNumber': '33333333', 'emailAddress': 'denial.roast@learningcontainer.com'}, {'userId': 4, 'firstName': 'devid', 'lastName': 'neo', 'phoneNumber': '222222222', 'emailAddress': 'devid.neo@learningcontainer.com'}, {'userId': 5, 'firstName': 'jone', 'lastName': 'mac', 'phoneNumber': '111111111', 'emailAddress': 'jone.mac@learningcontainer.com'}]}you can load more,yonghang@mtp~ $ curl -s walkerever.com/share/test/json/s6.json | qic -m ~/tmp/tm.py,json,yaml "tm.xxlen(_)" 
1 : {'users': [{'userId': 1, 'firstName': 'Krish', 'lastName': 'Lee', 'phoneNumber': '123456', 'emailAddress': 'krish.lee@learningcontainer.com'}, {'userId': 2, 'firstName': 'racks', 'lastName': 'jacson', 'phoneNumber': '123456', 'emailAddress': 'racks.jacson@learningcontainer.com'}, {'userId': 3, 'firstName': 'denial', 'lastName': 'roast', 'phoneNumber': '33333333', 'emailAddress': 'denial.roast@learningcontainer.com'}, {'userId': 4, 'firstName': 'devid', 'lastName': 'neo', 'phoneNumber': '222222222', 'emailAddress': 'devid.neo@learningcontainer.com'}, {'userId': 5, 'firstName': 'jone', 'lastName': 'mac', 'phoneNumber': '111111111', 'emailAddress': 'jone.mac@learningcontainer.com'}]}JSON to HTML_h and _zh are two functions for the convertion.  _h is to create plain HTML table while _zh makes collapse/expand possible.yonghang@mtp~ $ curl -s walkerever.com/share/test/json/s6.json | qic "_h"
<tt>
<tablestyle="border-collapse:collapse;;" border=1 >
<trclass="child-MPzoqOdFrYXQpqJzvSpl">
<tdvalign="top"><b>users</b></td>
    <td>
        <tablestyle="border-collapse:collapse;;" border=1 width="100%">
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#FFFFFF">
            <tdvalign="top"><b>userId</b></td>
            <td>1</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#FFFFFF">
            <tdvalign="top"><b>firstName</b></td>
            <td>Krish</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#FFFFFF">
            <tdvalign="top"><b>lastName</b></td>
            <td>Lee</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#FFFFFF">
            <tdvalign="top"><b>phoneNumber</b></td>
            <td>123456</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#FFFFFF">
            <tdvalign="top"><b>emailAddress</b></td>
            <td>krish.lee@learningcontainer.com</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#F1F1F1">
            <tdvalign="top"><b>userId</b></td>
            <td>2</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#F1F1F1">
            <tdvalign="top"><b>firstName</b></td>
            <td>racks</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#F1F1F1">
            <tdvalign="top"><b>lastName</b></td>
            <td>jacson</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#F1F1F1">
            <tdvalign="top"><b>phoneNumber</b></td>
            <td>123456</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#F1F1F1">
            <tdvalign="top"><b>emailAddress</b></td>
            <td>racks.jacson@learningcontainer.com</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#FFFFFF">
            <tdvalign="top"><b>userId</b></td>
            <td>3</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#FFFFFF">
            <tdvalign="top"><b>firstName</b></td>
            <td>denial</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#FFFFFF">
            <tdvalign="top"><b>lastName</b></td>
            <td>roast</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#FFFFFF">
            <tdvalign="top"><b>phoneNumber</b></td>
            <td>33333333</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#FFFFFF">
            <tdvalign="top"><b>emailAddress</b></td>
            <td>denial.roast@learningcontainer.com</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#F1F1F1">
            <tdvalign="top"><b>userId</b></td>
            <td>4</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#F1F1F1">
            <tdvalign="top"><b>firstName</b></td>
            <td>devid</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#F1F1F1">
            <tdvalign="top"><b>lastName</b></td>
            <td>neo</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#F1F1F1">
            <tdvalign="top"><b>phoneNumber</b></td>
            <td>222222222</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#F1F1F1">
            <tdvalign="top"><b>emailAddress</b></td>
            <td>devid.neo@learningcontainer.com</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#FFFFFF">
            <tdvalign="top"><b>userId</b></td>
            <td>5</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#FFFFFF">
            <tdvalign="top"><b>firstName</b></td>
            <td>jone</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#FFFFFF">
            <tdvalign="top"><b>lastName</b></td>
            <td>mac</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#FFFFFF">
            <tdvalign="top"><b>phoneNumber</b></td>
            <td>111111111</td>
        </tr>
        <trclass="child-WvkznPHasGyCxViXFeQH" style="background-color:#FFFFFF">
            <tdvalign="top"><b>emailAddress</b></td>
            <td>jone.mac@learningcontainer.com</td>
        </tr>
        </table>

    </td>
</tr>
</table>_h in HTML,usersuserId1firstNameKrishlastNameLeephoneNumber123456emailAddresskrish.lee@learningcontainer.comuserId2firstNamerackslastNamejacsonphoneNumber123456emailAddressracks.jacson@learningcontainer.comuserId3firstNamedeniallastNameroastphoneNumber33333333emailAddressdenial.roast@learningcontainer.comuserId4firstNamedevidlastNameneophoneNumber222222222emailAddressdevid.neo@learningcontainer.comuserId5firstNamejonelastNamemacphoneNumber111111111emailAddressjone.mac@learningcontainer.com</td>_zh table,<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> 
<script type="text/javascript"> 
    $(document).ready(function () { 
        $('tr.parent') .css("cursor", "pointer") .attr("title", "Click to expand/collapse") .click(function () { 
            $(this).siblings('.child-' + this.id).toggle(); 
        }); 
        $('tr[@class^=child-]').hide().children('td'); 
    }); 
</script>D(1)usersL(5)userId1firstNameKrishlastNameLeephoneNumber123456emailAddresskrish.lee@learningcontainer.comuserId2firstNamerackslastNamejacsonphoneNumber123456emailAddressracks.jacson@learningcontainer.comuserId3firstNamedeniallastNameroastphoneNumber33333333emailAddressdenial.roast@learningcontainer.comuserId4firstNamedevidlastNameneophoneNumber222222222emailAddressdevid.neo@learningcontainer.comuserId5firstNamejonelastNamemacphoneNumber111111111emailAddressjone.mac@learningcontainer.com</td>... to be continued.