json-viewer

谷歌浏览器直接打开json格式内容的接口地址,可以格式化显示接口返回值,保留key的双引号,支持图片链接预览

当前为 2020-01-15 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name json-viewer
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1
  5. // @description 谷歌浏览器直接打开json格式内容的接口地址,可以格式化显示接口返回值,保留key的双引号,支持图片链接预览
  6. // @author sgd
  7. // @match *://*/*
  8. // @grant none
  9. // @require https://code.jquery.com/jquery-3.4.1.min.js
  10. // @icon https://www.easyicon.net/api/resizeApi.php?id=501159&size=128
  11. // ==/UserScript==
  12.  
  13. // jquery.json-viewer 插件 开始
  14. (function($){
  15. /**
  16. * Check if arg is either an array with at least 1 element, or a dict with at least 1 key
  17. * @return boolean
  18. */
  19. function isCollapsable(arg) {
  20. return arg instanceof Object && Object.keys(arg).length > 0;
  21. }
  22.  
  23. /**
  24. * Check if a string represents a valid url
  25. * @return boolean
  26. */
  27. function isUrl(string) {
  28. var regexp = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;
  29. return regexp.test(string);
  30. }
  31.  
  32. /**
  33. * Transform a json object into html representation
  34. * @return string
  35. */
  36. function json2html(json, options) {
  37. var html = '';
  38. if (typeof json === 'string') {
  39. /* Escape tags */
  40. json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
  41. if (isUrl(json))
  42. html += '<a href="' + json + '" class="json-string">"' + json + '"</a>';
  43. else
  44. html += '<span class="json-string">"' + json + '"</span>';
  45. }
  46. else if (typeof json === 'number') {
  47. html += '<span class="json-literal">' + json + '</span>';
  48. }
  49. else if (typeof json === 'boolean') {
  50. html += '<span class="json-literal">' + json + '</span>';
  51. }
  52. else if (json === null) {
  53. html += '<span class="json-literal">null</span>';
  54. }
  55. else if (json instanceof Array) {
  56. if (json.length > 0) {
  57. html += '[<ol class="json-array">';
  58. for (var i = 0; i < json.length; ++i) {
  59. html += '<li>';
  60. /* Add toggle button if item is collapsable */
  61. if (isCollapsable(json[i])) {
  62. html += '<a href class="json-toggle"></a>';
  63. }
  64. html += json2html(json[i], options);
  65. /* Add comma if item is not last */
  66. if (i < json.length - 1) {
  67. html += ',';
  68. }
  69. html += '</li>';
  70. }
  71. html += '</ol>]';
  72. }
  73. else {
  74. html += '[]';
  75. }
  76. }
  77. else if (typeof json === 'object') {
  78. var key_count = Object.keys(json).length;
  79. if (key_count > 0) {
  80. html += '{<ul class="json-dict">';
  81. for (var key in json) {
  82. if (json.hasOwnProperty(key)) {
  83. html += '<li>';
  84. var keyRepr = options.withQuotes ?
  85. '<span class="json-string">"' + key + '"</span>' : key;
  86. /* Add toggle button if item is collapsable */
  87. if (isCollapsable(json[key])) {
  88. html += '<a href class="json-toggle">' + keyRepr + '</a>';
  89. }
  90. else {
  91. html += keyRepr;
  92. }
  93. html += ': ' + json2html(json[key], options);
  94. /* Add comma if item is not last */
  95. if (--key_count > 0)
  96. html += ',';
  97. html += '</li>';
  98. }
  99. }
  100. html += '</ul>}';
  101. }
  102. else {
  103. html += '{}';
  104. }
  105. }
  106. return html;
  107. }
  108.  
  109. /**
  110. * jQuery plugin method
  111. * @param json: a javascript object
  112. * @param options: an optional options hash
  113. */
  114. $.fn.jsonViewer = function(json, options) {
  115. options = options || {};
  116.  
  117. /* jQuery chaining */
  118. return this.each(function() {
  119.  
  120. /* Transform to HTML */
  121. var html = json2html(json, options);
  122. if (isCollapsable(json))
  123. html = '<a href class="json-toggle"></a>' + html;
  124.  
  125. /* Insert HTML in target DOM element */
  126. $(this).html(html);
  127.  
  128. /* Bind click on toggle buttons */
  129. $(this).off('click');
  130. $(this).on('click', 'a.json-toggle', function() {
  131. var target = $(this).toggleClass('collapsed').siblings('ul.json-dict, ol.json-array');
  132. target.toggle();
  133. if (target.is(':visible')) {
  134. target.siblings('.json-placeholder').remove();
  135. }
  136. else {
  137. var count = target.children('li').length;
  138. var placeholder = count + (count > 1 ? ' items' : ' item');
  139. target.after('<a href class="json-placeholder">' + placeholder + '</a>');
  140. }
  141. return false;
  142. });
  143.  
  144. /* Simulate click on toggle button when placeholder is clicked */
  145. $(this).on('click', 'a.json-placeholder', function() {
  146. $(this).siblings('a.json-toggle').click();
  147. return false;
  148. });
  149.  
  150. if (options.collapsed == true) {
  151. /* Trigger click to collapse all nodes */
  152. $(this).find('a.json-toggle').click();
  153. }
  154. });
  155. };
  156. })(jQuery);
  157. // jquery.json-viewer 插件 结束
  158.  
  159. (function() {
  160. 'use strict';
  161. // 添加样式
  162. var style = document.createElement("style");
  163. style.type = "text/css";
  164. var text = document.createTextNode("body{margin-bottom: 200px;}per{margin:20px;}#btn{position: fixed;top: 20px;right: 20px;background-color: transparent;border: 1px solid rgb(218, 220, 224);border-radius: 4px;box-sizing: border-box;color: rgb(26, 115, 232);cursor: pointer;line-height:30px;}#btn:hover{background-color:rgb(210, 227, 252);} ul.json-dict, ol.json-array {list-style-type: none;margin: 0 0 0 1px;border-left: 1px dotted #ccc;padding-left: 2em;}.json-string {color: #0B7500;}.json-literal {color: #1A01CC;font-weight: bold;}a.json-toggle {position: relative;color: inherit;text-decoration: none;}a.json-toggle:focus {outline: none;}a.json-toggle:before {color: #aaa;content: \"\\25BC\";position: absolute;display: inline-block;width: 1em;left: -1em;}a.json-toggle.collapsed:before {transform: rotate(-90deg);-ms-transform: rotate(-90deg);-webkit-transform: rotate(-90deg);}a.json-placeholder {color: #aaa;padding: 0 1em;text-decoration: none;} a.json-placeholder:hover { text-decoration: underline; }");
  165. style.appendChild(text);
  166. var head = document.getElementsByTagName("head")[0];
  167. head.appendChild(style);
  168.  
  169. var source = $('pre[style="word-wrap: break-word; white-space: pre-wrap;"]');
  170. // 如果是直接打开的json接口地址才需要格式化插件
  171. if(source.length > 0){
  172. source.attr("id", "json-source")
  173. source.hide();
  174. var src = source.html();// 获取到内容
  175. // 添加一个格式化显示的per元素
  176. $("body").append($('<per id="json-renderer"></pre>'))
  177. console.log(src);
  178. // 将内容用eval函数处理下
  179. var input = eval('(' + src + ')');
  180. // 调用格式化方法,参数:是否收缩所有的节点 是否为Key添加双引号
  181. $('#json-renderer').jsonViewer(input, {collapsed: false,withQuotes: true});
  182.  
  183. // 添加原文、格式化后内容的切换按钮
  184. $("body").append('<input type="button" value="View Source" id="btn"/>');
  185. $("body").on("click","#btn",function(){
  186. var v = $(this).val();
  187. if(v=='View Source'){
  188. $(this).val("Format Content");
  189. // 查看原文
  190. $('#json-renderer').hide();
  191. $('#json-source').show();
  192. }else{
  193. $(this).val("View Source");
  194. // 格式化
  195. $('#json-renderer').show();
  196. $('#json-source').hide();
  197. }
  198. });
  199.  
  200. // 所有a标签,看是否是图片,是图片生成预览图
  201. $(document).on("mouseenter mouseleave","a.json-string",function(event){
  202. if(event.type=='mouseenter'){
  203. // 移入
  204. var href = $(this).attr('href');
  205. if(isImg(href)){
  206. $("body").append('<div style="display:none; position: absolute;width:300px;height:200px;" class="preview"><img style="width:100%;height:100%;" src="'+ href +'" /></div>');
  207. var xPos = parseInt(event.pageX) + "px";
  208. var yPos = parseInt(event.pageY) + "px";
  209. $(".preview").css("left", xPos);
  210. $(".preview").css("top", yPos);
  211. $(".preview").show();
  212. }
  213. }else{
  214. // 移除
  215. $(".preview").remove();
  216. }
  217.  
  218. });
  219. }
  220.  
  221. /*检查是否是图片链接*/
  222. function isImg(pathImg) {
  223. var regexp = /^(http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?\/([\w#!:.?+=&%@!\-\/])*\.(gif|jpg|jpeg|png|GIF|JPG|PNG)([\w#!:.?+=&%@!\-\/])?/;
  224. return regexp.test(pathImg);
  225. }
  226.  
  227. })();