Explorar o código

JSON格式化支持排序:升序&降序

zxlie %!s(int64=5) %!d(string=hai) anos
pai
achega
c0a07299be

+ 60 - 19
apps/json-format/automatic.js

@@ -11,9 +11,21 @@ module.exports = (() => {
 
     "use strict";
 
+    const JSON_SORT_TYPE_KEY = 'json_sort_type_key';
+
+    // 用于记录最原始的json串
+    let originalJsonStr = '';
+    let curSortType = 0;
+    // JSONP形式下的callback name
+    let funcName = null;
+    let jsonObj = null;
+    let fnTry = null;
+    let fnCatch = null;
+
     let _htmlFragment = [
         '<style type="text/css">.mod-contentscript #formattingMsg{position:absolute;top:0;font-size:14px;color:#333;margin:5px;}#formattingMsg .x-loading{width:12px;height:12px;border:1px solid #f00;border-radius:50%;box-shadow:0 0 10px 2px;color:#c00;border-right-color:transparent;border-top-color:transparent;animation:spin-right 1s linear infinite normal;animation-delay:0s;margin:0 5px 0 0;display:inline-block}#formattingMsg .x-loading:before{display:block;width:8px;height:8px;margin:1px;border:2px solid #f00;content:" ";border-radius:50%;border-left-color:transparent;border-bottom-color:transparent}@keyframes spin-right{from{transform:rotate(0deg);opacity:.2}50%{transform:rotate(180deg);opacity:1.0}to{transform:rotate(360deg);opacity:.2}}</style>',
         '<div class="mod-json mod-contentscript"><div class="rst-item">',
+        '<div class="jf-sort" style="display:none"><span class="x-stitle">JSON排序:</span><label for="sort_null">默认</label><input type="radio" name="jsonsort" id="sort_null" value="0" checked="checked"><label for="sort_asc">升序</label><input type="radio" name="jsonsort" id="sort_asc" value="1"><label for="sort_desc">降序</label><input type="radio" name="jsonsort" id="sort_desc" value="-1"></div>',
         '<div id="formattingMsg"><span class="x-loading"></span>格式化中...</div>',
         '<div id="jfCallbackName_start" class="callback-name"></div>',
         '<div id="jfContent"></div>',
@@ -75,9 +87,10 @@ module.exports = (() => {
      * @param {Object} text
      */
     let _uniDecode = function (text) {
-        try{
+        try {
             text = decodeURIComponent(text);
-        }catch(e){}
+        } catch (e) {
+        }
         text = text.replace(/(\\)?\\u/gi, "%u").replace('%u0025', '%25');
 
         text = unescape(text.toString().replace(/%2B/g, "+"));
@@ -134,12 +147,6 @@ module.exports = (() => {
             source = _uniDecode(source);
         }
 
-        // JSONP形式下的callback name
-        let funcName = null;
-        let jsonObj = null;
-        let fnTry = null;
-        let fnCatch = null;
-
         // 下面校验给定字符串是否为一个合法的json
         try {
 
@@ -212,20 +219,54 @@ module.exports = (() => {
             _loadCss();
             $('body').html(_htmlFragment);
 
-            // 格式化
-            Tarp.require('../json-format/format-lib').format(source);
+            originalJsonStr = source;
 
-            // 如果是JSONP格式的,需要把方法名也显示出来
-            if (funcName != null) {
-                if (fnTry && fnCatch) {
-                    $('#jfCallbackName_start').html('<pre style="padding:0">' + fnTry + '</pre>' + funcName + '(');
-                    $('#jfCallbackName_end').html(')<br><pre style="padding:0">' + fnCatch + '</pre>');
-                } else {
-                    $('#jfCallbackName_start').html(funcName + '(');
-                    $('#jfCallbackName_end').html(')');
-                }
+            // 获取上次记录的排序方式
+            curSortType = parseInt(localStorage.getItem(JSON_SORT_TYPE_KEY) || 0);
+            _didFormat(curSortType);
+
+            // 初始化
+            $('[name=jsonsort][value=' + curSortType + ']').attr('checked', 1);
+            $('.jf-sort').slideDown(1000);
+
+            _bindSortEvent();
+        }
+    };
+
+    let _didFormat = function (sortType) {
+        sortType = sortType || 0;
+        let source = originalJsonStr;
+
+        if (sortType !== 0) {
+            let jsonObj = Tarp.require('../json-format/jsonabc').sortObj(JSON.parse(originalJsonStr), parseInt(sortType), true);
+            source = JSON.stringify(jsonObj);
+        }
+
+        // 格式化
+        Tarp.require('../json-format/format-lib').format(source);
+
+        // 如果是JSONP格式的,需要把方法名也显示出来
+        if (funcName != null) {
+            if (fnTry && fnCatch) {
+                $('#jfCallbackName_start').html('<pre style="padding:0">' + fnTry + '</pre>' + funcName + '(');
+                $('#jfCallbackName_end').html(')<br><pre style="padding:0">' + fnCatch + '</pre>');
+            } else {
+                $('#jfCallbackName_start').html(funcName + '(');
+                $('#jfCallbackName_end').html(')');
             }
         }
+
+        localStorage.setItem(JSON_SORT_TYPE_KEY, sortType);
+    };
+
+    let _bindSortEvent = function () {
+        $('[name=jsonsort]').click(function (e) {
+            let sortType = parseInt(this.value);
+            if (sortType !== curSortType) {
+                _didFormat(sortType);
+                curSortType = sortType;
+            }
+        });
     };
 
     return {

+ 0 - 2
apps/json-format/format-lib.js

@@ -767,8 +767,6 @@ let JsonFormatDealer = (function () {
     // Function to convert object to an HTML string
     function jsonObjToHTML(obj, jsonpFunctionName) {
 
-        // spin(5) ;
-
         // Format object (using recursive kvov builder)
         let rootKvov = getKvovDOM(obj, false);
 

+ 24 - 2
apps/json-format/index.css

@@ -40,7 +40,7 @@ body {
     padding: 10px;
 }
 #jsonSource,.CodeMirror {
-    height: calc(100% - 50px);
+    height: calc(100% - 70px);
     /*font-size: 10px;*/
 }
 #errorMsg {
@@ -166,7 +166,29 @@ input[type=checkbox] {
     padding-top: 0;
     text-align: left;
 }
-
+.x-sort {
+    display: block;
+    margin-left: 150px;
+}
+.x-sort .x-split {
+    display: none;
+}
+.layout-up-down .x-sort {
+    display: inline;
+    margin: 0;
+}
+.layout-up-down .x-sort .x-split {
+    margin: 0 20px;
+    color: #ccc;
+    display: inline;
+}
+.x-sort .x-stitle {
+    color: #f00;
+    font-weight: bold;
+}
+.x-sort input {
+    margin-right: 10px;
+}
 
 #layoutBar {margin-left:30px}
 #btnLeftRight,#btnUpDown{

+ 12 - 2
apps/json-format/index.html

@@ -15,7 +15,7 @@
                         <a href="http://www.baidufe.com/fehelper/feedback.html" target="_blank" class="x-a-high">
                             <img src="../static/img/fe-16.png" alt="fehelper"/> FeHelper</a>:JSON格式化查看
                         <span class="x-xdemo" ref="demoLink1" @click="setDemo">示例1:JSON片段</span>
-                        <a class="x-xdemo" href="https://www.sojson.com/api/qqmusic/8446666/json" target="_blank">示例2:在线JSON-1</a>
+                        <a class="x-xdemo" href="http://t.weather.sojson.com/api/weather/city/101030100" target="_blank">示例2:在线JSON-1</a>
 
                         <span id="layoutBar">
                             <button id="btnLeftRight" ref="btnLeftRight" class="selected" @click="changeLayout('left-right')">左右布局</button><button id="btnUpDown" ref="btnUpDown" @click="changeLayout('up-down')">上下布局</button>
@@ -31,7 +31,17 @@
                         <button id="btnFormat" class="btn btn-primary" @click="format">格式化</button>
                         <button id="btnCompress" class="btn btn-success" @click="compress">压缩</button>
                         <input type="checkbox" v-model="jsonLintSwitch" id="jsonLint" @click="lintOn"><label for="jsonLint">开启JSONLint</label>
-                        <input type="checkbox" v-model="overrideJson" id="jsonOvrd" @click="setCache"><label for="jsonOvrd">点选JSON项时默认进行编辑</label>
+                        <input type="checkbox" v-model="overrideJson" id="jsonOvrd" @click="setCache"><label for="jsonOvrd">选中JSON并编辑</label>
+                        <span class="x-sort">
+                            <span class="x-split">|</span>
+                            <span class="x-stitle">JSON排序:</span>
+                            <label for="sort_null">默认</label>
+                            <input type="radio" name="jsonsort" id="sort_null" value="0" checked @click="format">
+                            <label for="sort_asc">升序</label>
+                            <input type="radio" name="jsonsort" id="sort_asc" value="1" @click="format">
+                            <label for="sort_desc">降序</label>
+                            <input type="radio" name="jsonsort" id="sort_desc" value="-1" @click="format">
+                        </span>
                     </div>
                     <div id="errorTips" v-bind:style="{display:showTips?'block':'none'}">
                         <div id="errorBtn" @click="closeTips"><span id="closeError">☓</span></div>

+ 4 - 1
apps/json-format/index.js

@@ -115,7 +115,10 @@ new Vue({
             // 是json格式,可以进行JSON自动格式化
             if (jsonObj != null && typeof jsonObj === "object" && !this.errorMsg.length) {
                 try {
-                    // 要尽量保证格式化的东西一定是一个json,所以需要把内容进行JSON.stringify处理
+                    let sortType = document.querySelectorAll('[name=jsonsort]:checked')[0].value;
+                    if (sortType !== '0') {
+                        jsonObj = Tarp.require('../json-format/jsonabc').sortObj(jsonObj, parseInt(sortType), true);
+                    }
                     source = JSON.stringify(jsonObj);
                 } catch (ex) {
                     // 通过JSON反解不出来的,一定有问题

+ 74 - 0
apps/json-format/jsonabc.js

@@ -0,0 +1,74 @@
+/**
+ * JSON排序处理
+ * @type {{sort, sortObj, cleanJSON}}
+ */
+module.exports = (function () {
+
+    // Is a value an array?
+    function isArray(val) {
+        return Object.prototype.toString.call(val) === '[object Array]';
+    }
+
+    // Is a value an Object?
+    function isPlainObject(val) {
+        return Object.prototype.toString.call(val) === '[object Object]';
+    }
+
+    /**
+     * 排序算法
+     * @param un 需要排序的JSON
+     * @param asc 是否正序
+     * @param noarray 不包括数组,默认false
+     * @returns {{}}
+     */
+    function sortObj(un, asc, noarray) {
+        asc = asc !== -1 ? 1 : -1;
+        noarray = noarray || false;
+
+        let or = {};
+
+        // 如果是BigInt的对象,则不参与排序
+        if (typeof JSON.BigNumber === 'function' && un instanceof JSON.BigNumber) {
+            return un;
+        }
+
+        if (isArray(un)) {
+            // Sort or don't sort arrays
+            if (noarray) {
+                or = un;
+            } else {
+                or = un.sort();
+            }
+
+            or.forEach(function (v, i) {
+                or[i] = sortObj(v, asc, noarray);
+            });
+
+            if (!noarray) {
+                or = or.sort(function (a, b) {
+                    a = (typeof a === 'object') ? JSON.stringify(a) : a;
+                    b = (typeof b === 'object') ? JSON.stringify(b) : b;
+                    return a < b ? -1 * asc : (a > b ? 1 * asc : 0);
+                });
+            }
+        } else if (isPlainObject(un)) {
+            or = {};
+            Object.keys(un).sort(function (a, b) {
+                if (a.toLowerCase() < b.toLowerCase()) return -1 * asc;
+                if (a.toLowerCase() > b.toLowerCase()) return 1 * asc;
+                return 0;
+            }).forEach(function (key) {
+                or[key] = sortObj(un[key], asc, noarray);
+            });
+        } else {
+            or = un;
+        }
+
+        return or;
+    }
+
+    return {
+        sortObj: sortObj
+    };
+
+})();

+ 14 - 0
apps/json-format/without-ui.css

@@ -170,3 +170,17 @@ html body {
 #boxOpt a:hover {
     color:#f00;
 }
+
+.jf-sort {
+    position: absolute;
+    top: 6px;
+    right: 250px;
+    font-size: 12px;
+    color: #615b5b;
+}
+.jf-sort .x-stitle {
+    font-weight: bold;
+}
+.jf-sort input {
+    margin-right: 10px;
+}

+ 2 - 1
apps/manifest.json

@@ -1,6 +1,6 @@
 {
   "name": "WEB前端助手(FeHelper)-Dev",
-  "version": "2019.11.2717",
+  "version": "2019.12.1919",
   "manifest_version": 2,
   "default_locale": "zh_CN",
   "description": "Awesome,All In One的一个工具,包含多个独立小应用,比如:Json工具、代码美化、代码压缩、二维码、Postman、markdown、网页油猴、便签笔记、信息加密与解密、随机密码生成、Crontab等等!",
@@ -65,6 +65,7 @@
     "json-format/without-ui.css",
     "json-format/automatic.js",
     "json-format/format-lib.js",
+    "json-format/jsonabc.js",
     "qr-code/decode.js",
     "wpo/inject.js",
     "color-picker/index.js",