-
Notifications
You must be signed in to change notification settings - Fork 137
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Support For Responses Visualisation #511
Comments
Thanks @oliverdrummond for the feedback, will review and add to roadmap. |
+1. This one stops me from moving from Postman 😭 |
Hi @HomelessCoder as an alternative way, you can send that visualisation html as response for the request which will display graphs. just a suggestion for short term use. |
This is very much of interest to my team/company as well. The built-in table visualization of a JSON response is very helpful on larger response bodies, whether more complex JSON objects, number of JSON objects returned, or combination of the two. There are aspects that can be caught much easier in table form with easier comparison side by side than scrolling through JSON text. The import of raw JSON into Excel has proven useless given the number of manual steps involved and how it hides nested objects instead of surfacing them. This may work fine for objects with fewer properties or flatter objects, but that is not what we're working with. After looking at this capability in Postman again yesterday to gain the insight we needed, I see that there is not only a table visualization, but also options for a linear chart and a bar graph. I don't have readily available use cases for the charts/graphs, but having a sort or filter on the displayed table's columns would be VERY helpful, putting it far ahead of Postman's implementation, in my opinion. As far as altering the API to return HTML instead of JSON, that is not an option for us, as some of the endpoints that we're working with are a 3rd party's API. These are the ones that we're trying to get the most insight into, and have the least familiarity with, where the table visualization would be the most helpful. I have included the script below that we have used in the Tests tab in Postman to dynamically build a table from the JSON response. var template = `
<style>
.fill,
body,
html {
height: 100%
}
#json_vl,
.td_head,
.td_row_even,
.td_row_odd {
font-size: small
}
#json_pnl,
#xxa,
.navbar-header,
.navbar-nav,
.navbar-nav>li,
.td_head {
float: left
}
.fill {
min-height: 100%
}
#json_vl {
font-family: Consolas, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace
}
#widget {
width: 100%
}
.top_size {
height: 51px
}
#all_panels {
height: 100%;
min-height: 100%
}
#aboutLnk {
position: fixed;
right: 10px;
top: 15px
}
#inner_text {
display: block;
position: absolute;
height: auto;
bottom: 0;
top: 0;
left: 0;
right: 0;
margin-top: 51px;
margin-bottom: 0
}
#json_pnl {
background-color: #ccc;
width: 33.3%
}
#xxa {
background-color: #E8E8E8;
width: 66.7%
}
#table_pnl,
#tree_pnl {
background-color: #E8E8E8;
float: left;
width: 50%
}
#sharethis {
position: fixed;
right: 80px;
top: 10px
}
#inner_tbl {
padding-left: 2px
}
.td_row_even {
padding: 2px;
background-color: #F6F4F0
}
.td_row_odd {
padding: 2px;
background-color: #FFF
}
.td_head {
padding: 2px;
font-weight: 700
}
input,
p,
select,
td,
textarea,
th {
font-size: 1em
}
table,
td,
th {
border: 1px solid gray
}
textarea {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
display: block;
width: 100%;
height: 100%;
margin: 0;
padding: 4px;
border: 1px solid #333;
overflow-y: auto;
overflow-x: hidden
}
*,
html {
font-family: Verdana, Arial, Helvetica, sans-serif
}
form,
h1,
h2,
h3,
h4,
h5,
li,
p,
ul {
margin: 0;
padding: 0
}
img {
border: none
}
p {
margin: 0 0 1em
}
table {
font-size: 100%;
background-color: white;
}
ol.tree {
padding: 0 0 0 30px;
width: 300px
}
li {
position: relative;
margin-left: -15px;
list-style: none
}
li.file {
margin-left: -1px !important
}
li.file a {
color: #000;
padding-left: 12px;
text-decoration: none;
display: block;
font-size: small
}
li.file a[href$='.css'],
li.file a[href$='.js'],
li.file a[href*='.pdf']
li input {
position: absolute;
left: 0;
margin-left: 0;
opacity: 0;
z-index: 2;
cursor: pointer;
height: 1em;
width: 1em;
top: 0
}
li input+ol {
margin: -20px 0 0 -44px;
height: 1em;
padding: 1.563em 0 0 80px
}
li label.lbl_array,
li label.lbl_obj {
display: block;
padding-left: 33px;
margin-bottom: 2px
}
li input+ol>li {
display: none;
margin-left: -14px !important;
padding-left: 1px
}
li label.lbl_obj {
cursor: pointer
}
li label.lbl_array {
cursor: pointer
}
li input:checked+ol {
margin: -20px 0 0 -44px;
padding: 1.563em 0 0 80px;
height: auto
}
li input:checked+ol>li {
display: block;
margin: 0 0 .125em
}
li input:checked+ol>li:last-child {
margin: 0 0 .063em
}
.container {
width: 970px;
max-width: none !important
}
.col-xs-4 {
padding-top: 15px;
padding-bottom: 15px;
background-color: #eee;
background-color: rgba(86, 61, 124, .15);
border: 1px solid #ddd;
border: 1px solid rgba(86, 61, 124, .2)
}
</style>
<div id="html">
<input type="text" id="json">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!--<script src="json2table.js"></script>-->
<script>
$(function() {
pm.getData((err, data) => {
$("#json").val(JSON.stringify(data.json));
json2table("#html");
});
});
function call(a) {
$("#json").val(JSON.stringify(a, void 0, 2));
json2table()
}
function json2table(selector) {
$(selector).html(buildTable(getJsonVar()));
}
function getJsonVar() {
try {
var a = $.parseJSON($("#json").val());
$("#json").val(JSON.stringify(a, void 0, 2));
return a
} catch (e) {
alert(e);
}
}
function buildTable(a) {
var e = document.createElement("table"),
d, b;
if (isArray(a)) return buildArray(a);
for (var c in a) "object" != typeof a[c] || isArray(a[c]) ? "object" == typeof a[c] && isArray(a[c]) ? (d = e.insertRow(-1), b = d.insertCell(-1), b.colSpan = 2, b.innerHTML = '<div class="td_head">' + encodeText(c) + '</div><table style="width:100%">' + $(buildArray(a[c]), !1).html() + "</table>") : (d = e.insertRow(-1), b = d.insertCell(-1), b.innerHTML = "<div class='td_head'>" + encodeText(c) + "</div>", d = d.insertCell(-1), d.innerHTML = "<div class='td_row_even'>" +
encodeText(a[c]) + "</div>") : (d = e.insertRow(-1), b = d.insertCell(-1), b.colSpan = 2, b.innerHTML = '<div class="td_head">' + encodeText(c) + '</div><table style="width:100%">' + $(buildTable(a[c]), !1).html() + "</table>");
return e
}
function buildArray(a) {
var e = document.createElement("table"),
d, b, c = !1,
p = !1,
m = {},
h = -1,
n = 0,
l;
l = "";
if (0 == a.length) return "<div></div>";
d = e.insertRow(-1);
for (var f = 0; f < a.length; f++)
if ("object" != typeof a[f] || isArray(a[f])) "object" == typeof a[f] && isArray(a[f]) ? (b = d.insertCell(h), b.colSpan = 2, b.innerHTML = '<div class="td_head"></div><table style="width:100%">' + $(buildArray(a[f]), !1).html() + "</table>", c = !0) : p || (h += 1, p = !0, b = d.insertCell(h), m.empty = h, b.innerHTML = "<div class='td_head'> </div>");
else
for (var k in a[f]) l =
"-" + k, l in m || (c = !0, h += 1, b = d.insertCell(h), m[l] = h, b.innerHTML = "<div class='td_head'>" + encodeText(k) + "</div>");
c || e.deleteRow(0);
n = h + 1;
for (f = 0; f < a.length; f++)
if (d = e.insertRow(-1), td_class = isEven(f) ? "td_row_even" : "td_row_odd", "object" != typeof a[f] || isArray(a[f]))
if ("object" == typeof a[f] && isArray(a[f]))
for (h = m.empty, c = 0; c < n; c++) b = d.insertCell(c), b.className = td_class, l = c == h ? '<table style="width:100%">' + $(buildArray(a[f]), !1).html() + "</table>" : " ", b.innerHTML = "<div class='" + td_class + "'>" + encodeText(l) +
"</div>";
else
for (h = m.empty, c = 0; c < n; c++) b = d.insertCell(c), l = c == h ? a[f] : " ", b.className = td_class, b.innerHTML = "<div class='" + td_class + "'>" + encodeText(l) + "</div>";
else {
for (c = 0; c < n; c++) b = d.insertCell(c), b.className = td_class, b.innerHTML = "<div class='" + td_class + "'> </div>";
for (k in a[f]) c = a[f], l = "-" + k, h = m[l], b = d.cells[h], b.className = td_class, "object" != typeof c[k] || isArray(c[k]) ? "object" == typeof c[k] && isArray(c[k]) ? b.innerHTML = '<table style="width:100%">' + $(buildArray(c[k]), !1).html() + "</table>" : b.innerHTML =
"<div class='" + td_class + "'>" + encodeText(c[k]) + "</div>" : b.innerHTML = '<table style="width:100%">' + $(buildTable(c[k]), !1).html() + "</table>"
}
return e
}
function encodeText(a) {
return $("<div />").text(a).html()
}
function isArray(a) {
return "[object Array]" === Object.prototype.toString.call(a)
}
function isEven(a) {
return 0 == a % 2
}
</script>`;
// In case you only want a specific property, change it here.
//
// Default: You can set the entire JSON response using pm.response.json()
let tableProps = {
json: pm.response.json()
};
pm.visualizer.set(template, tableProps); |
Hi @cw1934 is your team using thunder client free or paid version? what is your team size? |
@rangav Our company is already on a paid plan. We are currently 12 users across 2 teams, growing team by team as ThunderClient proves full-featured enough for each team. Total department is 50+. |
Thanks @cw1934 for clarifying can you please confirm your company using below form. |
Hello, just want to add my name to the list of people saying this would be great. My team and I currently use Postman, but we are switching to Thunderclient (I think our director is still working on getting licenses purchased). We do use a few visualizations and would love to have that, but here's a different use case. My team and I use Thunderclient/Postman for working with APIs in our company - we are not developing/testing our own APIs but using Thunderclient as just a way to consume these APIs. So there are many cases where we get lots of data back then have to parse out certain sections of it based on various requirements. Typically what we do is use the code button to grab the curl command. Then we jump down to the cli and run the curl command piped to a jq command.
(the jq is just grouping together things based on the use_type) This is just example fake data - the normal response has a ton of data. But here's a small working example of fake json that the jq above will parse: {
"result": [
{
"name": "foo1",
"network_address": { "use_types": [ "cp" ] }
},
{
"name": "foo2",
"network_address": { "use_types": [ "w" ] }
},
{
"name": "foo3",
"network_address": { "use_types": [ "cp" ] }
},
{
"name": "foo4",
"network_address": { "use_types": [ "w" ] }
}
]
} And here's an example of the output that jq returns: [
{
"use_type": "cp",
"names": [
"foo1",
"foo3"
]
},
{
"use_type": "w",
"names": [
"foo2",
"foo4"
]
}
] Not everyone on our team is familiar with code or jq, so they do a lot of copy/pasting. I would love to have something like this saved with the request itself so that I could then create a bunch of canned queries for my teammates. Hopefully I've made that clear, but let me know if any questions or clarification needed. Thanks for the fantastic tool! |
Thanks @seanwcom for the feedback, This feature is on the priority list now. Planning to implement next month. Do you mind sharing your company name using below form |
Sure thing - I sent a contact request. Thanks! |
This feature is implemented and published to the marketplace, please update to See all features in this update Please test and let me know your feedback. |
I've finally had a chance to do some initial testing with this and its great so far. I've been able to fully recreate what I was doing in Postman, thank you! Here's an idea for a bit more functionality. One of the APIs we regularly consume has close to a 60 second response time (ugh...). What do you think about a way to refresh the chart without requerying the API? Obviously this doesn't get new data, but it would be helpful while editing the inline script's handlebars template, refreshing the display (instantly) without having to constantly hit the API. |
Thanks @seanwcom for the feedback. Will check if it's easy to refresh chart without executing the api request. |
We're trying to get this to work on our end, but haven't been successful yet. I'm not sure if it's the JSON response schema that we're testing with, or if we're missing some step completely. Can the following 3 pieces for a working visualization be added here (or release notes) so we can better determine if we really have all the right pieces in place?
|
@cw1934 - Here's a really simple one I just threw together, see if you can get this working. This is a simple GET request to some public sample data: https://jsonplaceholder.typicode.com/users Drop this in your Tests, Scripting tab: var template = `
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.8/handlebars.min.js"></script>
<div id="output"></div>
<script id="entry-template" type="text/x-handlebars-template">
{{#each this}}
{{name}}<br>
{{/each}}
</script>
<script>
var source = document.getElementById("entry-template").innerHTML;
var template = Handlebars.compile(source);
document.getElementById("output").innerHTML = template(chart_data);
</script>
`;
var data = tc.response.json;
tc.chartHTML(template, data); Since the response json is an array, I'm looping with |
@seanwcom Thanks so much for the sample, that helped us get past our initial hold-up. To everyone; |
The template we did get to work borrows from seanwcom's response above. Replacing the 3-line 'each' block with this: |
@rangav - do you prefer any other issues with the chart stuff here in this thread or a new issue? Not sure how you prefer it since this is still a beta feature. It seems that I can't copy text from the chart. I can select text, but cmd-c does not copy (I'm on a mac if that makes a difference). |
@seanwcom you can create a new issue, if its related to copy/paste issue. |
@CharlieSnowCode and @cw1934 will provide a universal solution example for converting JSON to HTML table in 1 or 2 days. |
Here is generic example below to convert any response JSON array to HTML Table You can modify the style as needed var response = tc.response.json;
var html = `
<style>
body {
font-size: 13px;
font-family: "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
table {
width: 100%;
box-sizing: border-box;
border-collapse: collapse;
border-spacing: 0;
}
td,
th {
padding: 0;
}
th, td {
padding: 4px 6px;
text-align: left;
border-bottom: 1px solid #E1E1E1;
}
th:first-child,
td:first-child {
padding-left: 0;
}
th:last-child,
td:last-child {
padding-right: 0;
}
</style>
<div id="container"></div>
<script>
// get the container element
let container = document.getElementById("container");
var cols = Object.keys(chart_data[0]);
var headerRow = '<tr>';
var bodyRows = '';
cols.map(function(col) {
headerRow += '<th>' + col + '</th>';
});
headerRow += '</tr>';
chart_data.map(function(row) {
bodyRows += '<tr>';
cols.map(function(colName) {
bodyRows += '<td>' + row[colName] + '</td>';
})
bodyRows += '</tr>';
});
var tabledata= '<table>' + headerRow + bodyRows + '</table>';
container.innerHTML = tabledata; // set table html
</script>`
tc.chartHTML(html, response); |
Thank you very much, worked like a charm! |
@rangav Thanks for the example, much appreciated! |
Thanks @CharlieSnowCode, @cw1934 for the feedback, Let me know if you need any further improvements. |
Is your feature request related to a problem? Please describe.
I cannot see my responses as a table format in Thunder Client. So, to have this visualisation I need to copy the response, save it as a JSON file and import it in Microsoft Excel
Describe the solution you'd like
Have an option to view the responses in a table format without extra software
Describe alternatives you've considered
1- To convert the JSON responses to a table format
2- Allow users to create JS codes to visualise it (like Postman Visualiser )
Implementation:
I use this code in my Postman "Tests" area. This way, I can see the table in the "Visualize".
The text was updated successfully, but these errors were encountered: