精华内容
下载资源
问答
  • 保留地图中的按键顺序 可以JSON序列化/反序列化 用法 package main import ( "encoding/json" "github.com/iancoleman/orderedmap" ) func main () { // use New() instead of o := map[string]interface{}{} ...
  • JSON

    千次阅读 多人点赞 2019-08-23 16:13:01
    (一)JSON 教程 (二)JSON 语法 (三)JSON 对象 (四)JSON 数组 (五)JSON.parse() (六)JSON.stringify() (七)JSON 使用 (八)JSONP 教程

    (一)JSON 教程

    • JSON: JavaScript Object Notation(JavaScript 对象表示法)

    • JSON 是存储和交换文本信息的语法。类似 XML。

    • JSON 比 XML 更小、更快,更易解析。

    {
    “sites”: [
    { “name”:“菜鸟教程” , “url”:“www.runoob.com” },
    { “name”:“google” , “url”:“www.google.com” },
    { “name”:“微博” , “url”:“www.weibo.com” }
    ]
    }

    1.什么是 JSON ?
    • JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
    • JSON 是轻量级的文本数据交换格式
    • JSON 独立于语言:JSON 使用 Javascript语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。 目前非常多的动态(PHP,JSP,.NET)编程语言都支持JSON。
    • JSON 具有自我描述性,更易理解
    2.JSON - 转换为 JavaScript 对象
    • JSON 文本格式在语法上与创建 JavaScript 对象的代码相同。

    • 由于这种相似性,无需解析器,JavaScript 程序能够使用内建的 eval() 函数,用 JSON 数据来生成原生的 JavaScript 对象。

    3.实例
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    <h2>JavaScript 创建 JSON 对象</h2>
    <p>
    网站名称: <span id="jname"></span><br /> 
    网站地址: <span id="jurl"></span><br /> 
    网站 slogan: <span id="jslogan"></span><br /> 
    </p>
    <script>
    var JSONObject= {
        "name":"菜鸟教程",
        "url":"www.runoob.com", 
        "slogan":"学的不仅是技术,更是梦想!"
    };
    document.getElementById("jname").innerHTML=JSONObject.name 
    document.getElementById("jurl").innerHTML=JSONObject.url 
    document.getElementById("jslogan").innerHTML=JSONObject.slogan
    </script>
     
    </body>
    </html>
    
    

    在这里插入图片描述

    4.与 XML 相同之处
    • JSON 是纯文本
    • JSON 具有"自我描述性"(人类可读)
    • JSON 具有层级结构(值中存在值)
    • JSON 可通过 JavaScript 进行解析
    • JSON 数据可使用 AJAX 进行传输
    5.与 XML 不同之处
    • 没有结束标签
    • 更短
    • 读写的速度更快
    • 能够使用内建的 JavaScript eval() 方法进行解析
    • 使用数组
    • 不使用保留字
    6.为什么使用 JSON?

    对于 AJAX 应用程序来说,JSON 比 XML 更快更易使用:

    • 使用 XML:
      读取 XML 文档
      使用 XML DOM 来循环遍历文档
      读取值并存储在变量中
    • 使用 JSON:
      读取 JSON 字符串
      用 eval() 处理 JSON 字符串

    (二)JSON 语法

    JSON 语法是 JavaScript 语法的子集。

    1.JSON 语法规则
    • 数据在名称/值对中
    • 数据由逗号分隔
    • 大括号保存对象
    • 中括号保存数组
    2.JSON 名称/值对

    JSON 数据的书写格式是:名称/值对。

    名称/值对包括字段名称(在双引号中),后面写一个冒号,然后是值:

    {
    key1:value1,
    key2:value2,

    }

    “name” : “菜鸟教程”

    这很容易理解,等价于这条 JavaScript 语句:

    name = “菜鸟教程”

    3.JSON 值

    数字(整数或浮点数)
    字符串(在双引号中)
    逻辑值(true 或 false)
    数组(在中括号中)
    对象(在大括号中)
    null

    4.JSON 数字

    JSON 数字可以是整型或者浮点型:

    { “age”:30 }

    5.JSON 对象

    JSON 对象在大括号({})中书写:

    对象可以包含多个名称/值对:

    { “name”:“菜鸟教程” , “url”:“www.runoob.com” }

    这一点也容易理解,与这条 JavaScript 语句等价:

    name = “菜鸟教程”
    url = “www.runoob.com”

    6.JSON 数组

    JSON 数组在中括号中书写:

    数组可包含多个对象:

    {
    “sites”: [
    { “name”:“菜鸟教程” , “url”:“www.runoob.com” },
    { “name”:“google” , “url”:“www.google.com” },
    { “name”:“微博” , “url”:“www.weibo.com” }
    ]
    }

    在上面的例子中,对象 “sites” 是包含三个对象的数组。每个对象代表一条关于某个网站(name、url)的记录。

    7.JSON 布尔值

    JSON 布尔值可以是 true 或者 false:

    { “flag”:true }

    8.JSON null

    JSON 可以设置 null 值:

    { “runoob”:null }

    9.JSON 使用 JavaScript 语法

    因为 JSON 使用 JavaScript 语法,所以无需额外的软件就能处理 JavaScript 中的 JSON。

    通过 JavaScript,您可以创建一个对象数组,并像这样进行赋值:

    var sites = [
    { “name”:“runoob” , “url”:“www.runoob.com” },
    { “name”:“google” , “url”:“www.google.com” },
    { “name”:“微博” , “url”:“www.weibo.com” }
    ];

    可以像这样访问 JavaScript 对象数组中的第一项(索引从 0 开始)

    sites[0].name;

    返回的内容是:runoob

    可以像这样修改数据:

    sites[0].name=“菜鸟教程”;

    eg:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    <h2>JavaScript 创建 JSON 对象</h2>
    <p>第一个网站名称: <span id="name1"></span></p> 
    <p>第一个网站修改后的名称: <span id="name2"></span></p> 
    
    <script>
    var sites = [
    	{ "name":"runoob" , "url":"www.runoob.com" }, 
    	{ "name":"google" , "url":"www.google.com" }, 
    	{ "name":"微博" , "url":"www.weibo.com" }
    ];
    
    document.getElementById("name1").innerHTML=sites[0].name;
    // 修改网站名称
    sites[0].name="菜鸟教程";
    document.getElementById("name2").innerHTML=sites[0].name;
    </script>
    
    </body>
    </html>
    

    在这里插入图片描述

    10.JSON 文件
    • JSON 文件的文件类型是 “.json”
    • JSON 文本的 MIME 类型是 “application/json”

    (三)JSON 对象

    1.对象语法

    实例:

    { “name”:“runoob”, “alexa”:10000, “site”:null }
    JSON 对象使用在大括号({})中书写。

    对象可以包含多个 key/value(键/值)对。

    key 必须是字符串,value 可以是合法的 JSON 数据类型(字符串, 数字, 对象, 数组, 布尔值或 null)。

    key 和 value 中使用冒号(:)分割。

    每个 key/value 对使用逗号(,)分割。

    2.访问对象值
    • 可以使用点号(.)来访问对象的值:
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <p>你可以使用点号(.)来访问 JSON 对象的值:</p>
    
    <p id="demo"></p>
    
    <script>
    
    var myObj, x;
    myObj = { "name":"runoob", "alexa":10000, "site":null };
    x = myObj.name;
    document.getElementById("demo").innerHTML = x;
    
    </script>
    
    </body>
    </html>
    

    在这里插入图片描述

    • 也可以使用中括号([])来访问对象的值:
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <p>你也可以使用中括号([])来访问 JOSN 对象的值:</p>
    
    <p id="demo"></p>
    
    <script>
    
    var myObj, x;
    myObj = myObj = { "name":"runoob", "alexa":10000, "site":null };
    x = myObj["name"];
    document.getElementById("demo").innerHTML = x;
    
    </script>
    
    </body>
    </html>
    

    在这里插入图片描述

    3.循环对象
    • 可以使用 for-in 来循环对象的属性:
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <p>使用 for-in 来循环对象的属性:</p>
    
    <p id="demo"></p>
    
    <script>
    var myObj = { "name":"runoob", "alexa":10000, "site":null };
    for (x in myObj) {
        document.getElementById("demo").innerHTML += x + "<br>";
    }
    </script>
    
    </body>
    </html>
    
    

    在这里插入图片描述

    • 在 for-in 循环对象的属性时,使用中括号([])来访问属性的值:
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <p>for-in 循环对象的属性时,使用中括号([])来访问属性的值:</p>
    
    <p id="demo"></p>
    
    <script>
    var myObj = { "name":"runoob", "alexa":10000, "site":null };
    for (x in myObj) {
        document.getElementById("demo").innerHTML += myObj[x] + "<br>";
    }
    </script>
    
    </body>
    </html>
    
    

    在这里插入图片描述

    4.嵌套 JSON 对象
    • JSON 对象中可以包含另外一个 JSON 对象:

    在这里插入图片描述

    • 你可以使用点号(.)或者中括号([])来访问嵌套的 JSON 对象
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <p>访问 JSON 内嵌对象。</p>
    
    <p id="demo"></p>
    
    <script>
    myObj = {
    	"name":"runoob",
    	"alexa":10000,
    	"sites": {
    		"site1":"www.runoob.com",
    		"site2":"m.runoob.com",
    		"site3":"c.runoob.com"
    	}
    }
    document.getElementById("demo").innerHTML += myObj.sites.site1 + "<br>";
    // 或者
    document.getElementById("demo").innerHTML += myObj.sites["site1"];
    </script>
    
    </body>
    </html>
    
    

    在这里插入图片描述

    5.修改值
    • 可以使用点号(.)来修改 JSON 对象的值:
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <p>修改 JSON 对象的值。</p>
    
    <p id="demo"></p>
    
    <script>
    var myObj, i, x = "";
    myObj = {
        "name":"runoob",
        "alexa":10000,
        "sites": {
            "site1":"www.runoob.com",
            "site2":"m.runoob.com",
            "site3":"c.runoob.com"
        }
    }
    myObj.sites.site1 = "www.google.com";
    
    for (i in myObj.sites) {
        x += myObj.sites[i] + "<br>";
    }
    
    document.getElementById("demo").innerHTML = x;
    
    </script>
    
    </body>
    </html>
    

    在这里插入图片描述

    • 可以使用中括号([])来修改 JSON 对象的值:
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <p>使用中括号([])来修改 JSON 对象的值。</p>
    
    <p id="demo"></p>
    
    <script>
    var myObj, i, x = "";
    myObj = {
        "name":"runoob",
        "alexa":10000,
        "sites": {
            "site1":"www.runoob.com",
            "site2":"m.runoob.com",
            "site3":"c.runoob.com"
        }
    }
    myObj.sites["site1"] = "www.google.com";
    
    for (i in myObj.sites) {
        x += myObj.sites[i] + "<br>";
    }
    
    document.getElementById("demo").innerHTML = x;
    
    </script>
    
    </body>
    </html>
    
    6.删除对象属性
    • 可以使用 delete 关键字来删除 JSON 对象的属性:
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body><p>删除 JSON 对象属性。</p><p id="demo"></p><script>
    var myObj, i, x = "";
    myObj = {
        "name":"runoob",
        "alexa":10000,
        "sites": {
            "site1":"www.runoob.com",
            "site2":"m.runoob.com",
            "site3":"c.runoob.com"
        }
    }
    delete myObj.sites.site1;for (i in myObj.sites) {
        x += myObj.sites[i] + "<br>";
    }
    ​
    document.getElementById("demo").innerHTML = x;</script></body>
    </html>
    

    在这里插入图片描述

    • 可以使用中括号([])来删除 JSON 对象的属性:
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <p>删除 JSON 对象属性。</p>
    
    <p id="demo"></p>
    
    <script>
    var myObj, i, x = "";
    myObj = {
        "name":"runoob",
        "alexa":10000,
        "sites": {
            "site1":"www.runoob.com",
            "site2":"m.runoob.com",
            "site3":"c.runoob.com"
        }
    }
    delete myObj.sites["site1"];
    
    for (i in myObj.sites) {
        x += myObj.sites[i] + "<br>";
    }
    
    document.getElementById("demo").innerHTML = x;
    
    </script>
    
    </body>
    </html>
    

    在这里插入图片描述

    (四)JSON 数组

    1.数组作为 JSON 对象

    实例
    [ “Google”, “Runoob”, “Taobao” ]

    JSON 数组在中括号中书写。

    JSON 中数组值必须是合法的 JSON 数据类型(字符串, 数字, 对象, 数组, 布尔值或 null)。

    JavaScript 中,数组值可以是以上的 JSON 数据类型,也可以是 JavaScript 的表达式,包括函数,日期,及 undefined。

    2.JSON 对象中的数组
    • 对象属性的值可以是一个数组:

    实例
    {
    “name”:“网站”,
    “num”:3,
    “sites”:[ “Google”, “Runoob”, “Taobao” ]
    }

    • 可以使用索引值来访问数组:
     <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <p>访问 JSON 对象数组值。</p>
    
    <p id="demo"></p>
    
    <script>
    
    var myObj, x;
    myObj = {
    	"name":"网站",
    	"num":3,
    	"sites":[ "Google", "Runoob", "Taobao" ]
    }
    x = myObj.sites[0];
    document.getElementById("demo").innerHTML = x;
    
    </script>
    
    </body>
    </html>
    

    在这里插入图片描述

    3.循环数组
    • 可以使用 for-in 来访问数组:
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <p>你可以使用 for-in 来访问数组:</p>
    
    <p id="demo"></p>
    
    <script>
    
    var myObj, i, x = "";
    myObj = {
    	"name":"网站",
    	"num":3,
    	"sites":[ "Google", "Runoob", "Taobao" ]
    };
    
    for (i in myObj.sites) {
        x += myObj.sites[i] + "<br>";
    }
    
    document.getElementById("demo").innerHTML = x;
    
    </script>
    
    </body>
    </html> 
    

    在这里插入图片描述

    • 也可以使用 for 循环:
     <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <p>使用 for 循环访问数组:</p>
    
    <p id="demo"></p>
    
    <script>
    
    var myObj, i, x = "";
    myObj = {
    	"name":"网站",
    	"num":3,
    	"sites":[ "Google", "Runoob", "Taobao" ]
    };
    
    for (i = 0; i < myObj.sites.length; i++) {
        x += myObj.sites[i] + "<br>";
    }
    
    document.getElementById("demo").innerHTML = x;
    
    </script>
    
    </body>
    </html>
    

    在这里插入图片描述

    4.嵌套 JSON 对象中的数组
    • JSON 对象中数组可以包含另外一个数组,或者另外一个 JSON 对象:

    实例
    myObj = {
    “name”:“网站”,
    “num”:3,
    “sites”: [
    { “name”:“Google”, “info”:[ “Android”, “Google 搜索”, “Google 翻译” ] },
    { “name”:“Runoob”, “info”:[ “菜鸟教程”, “菜鸟工具”, “菜鸟微信” ] },
    { “name”:“Taobao”, “info”:[ “淘宝”, “网购” ] }
    ]
    }

    • 可以使用 for-in 来循环访问每个数组:
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <p>循环内嵌数组:</p>
    
    <p id="demo"></p>
    
    <script>
    
    var myObj, i, j, x = "";
    myObj = {
        "name":"网站",
        "num":3,
        "sites": [
            { "name":"Google", "info":[ "Android", "Google 搜索", "Google 翻译" ] },
            { "name":"Runoob", "info":[ "菜鸟教程", "菜鸟工具", "菜鸟微信" ] },
            { "name":"Taobao", "info":[ "淘宝", "网购" ] }
        ]
    }
    
    for (i in myObj.sites) {
        x += "<h1>" + myObj.sites[i].name + "</h1>";
        for (j in myObj.sites[i].info) {
            x += myObj.sites[i].info[j] + "<br>";
        }
    }
    
    document.getElementById("demo").innerHTML = x;
    
    </script>
    
    </body>
    </html> 
    

    在这里插入图片描述

    5.修改数组值
    • 可以使用索引值来修改数组值:
     <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <p>修改 JSON 对象数组值。</p>
    
    <p id="demo"></p>
    
    <script>
    
    var myObj, i, x = "";
    myObj = {
    	"name":"网站",
    	"num":3,
    	"sites":[ "Google", "Runoob", "Taobao" ]
    };
     myObj.sites[1] = "Github";
    
    for (i in myObj.sites) {
        x += myObj.sites[i] + "<br>";
    }
    
    document.getElementById("demo").innerHTML = x;
    
    </script>
    
    </body>
    </html>
    

    在这里插入图片描述

    6.删除数组元素
    • 可以使用 delete 关键字来删除数组元素:
     <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <p>删除数组元素</p>
    
    <p id="demo"></p>
    
    <script>
    var myObj, i, x = "";
    myObj = {
    	"name":"网站",
    	"num":3,
    	"sites":[ "Google", "Runoob", "Taobao" ]
    };
    delete myObj.sites[1];
    
    for (i in myObj.sites) {
        x += myObj.sites[i] + "<br>";
    }
    
    document.getElementById("demo").innerHTML = x;
    
    </script>
    
    </body>
    </html>
    

    在这里插入图片描述

    (五)JSON.parse()

    JSON 通常用于与服务端交换数据。

    在接收服务器数据时一般是字符串。

    我们可以使用 JSON.parse() 方法将数据转换为 JavaScript 对象。

    • 语法

    JSON.parse(text[, reviver])

    • 参数说明:
      • text:必需, 一个有效的 JSON 字符串。
      • reviver: 可选,一个转换结果的函数, 将为对象的每个成员调用此函数。
    1.JSON 解析实例

    例如我们从服务器接收了以下数据:

    { “name”:“runoob”, “alexa”:10000, “site”:“www.runoob.com” }

    我们使用 JSON.parse() 方法处理以上数据,将其转换为 JavaScript 对象:

    var obj = JSON.parse(’{ “name”:“runoob”, “alexa”:10000, “site”:“www.runoob.com” }’);

    解析前要确保你的数据是标准的 JSON 格式,否则会解析出错。
    你可以使用我们的在线工具检测:https://c.runoob.com/front-end/53。

    解析完成后,我们就可以在网页上使用 JSON 数据了:

     <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <h2>JSON 对象中创建 JavaScript 对象</h2>
    
    <p id="demo"></p>
    
    <script>
    var obj = JSON.parse('{ "name":"runoob", "alexa":10000, "site":"www.runoob.com" }');
    document.getElementById("demo").innerHTML = obj.name + ":" + obj.site;
    </script>
    
    </body>
    </html>
     
    

    在这里插入图片描述

    2.从服务端接收 JSON 数据
    • 我们可以使用 AJAX 从服务器请求 JSON 数据,并解析为 JavaScript 对象。
     <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <h2>使用 XMLHttpRequest 来获取文件内容</h2>
    <p>文件内容是标准的 JSON 格式,可以使用 JSON.parse 方法将其转换为 JavaScript 对象。</p>
    
    <p id="demo"></p>
    
    <script>
    
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            myObj = JSON.parse(this.responseText);
            document.getElementById("demo").innerHTML = myObj.name;
        }
    };
    xmlhttp.open("GET", "/try/ajax/json_demo.txt", true);
    xmlhttp.send();
    
    </script>
    
    <p>查看 JSON 文件数据 <a href="/try/ajax/json_demo.txt" target="_blank">json_demo.txt</a></p>
    
    </body> 
    </html>
     
    

    在这里插入图片描述

    2.1 XMLHttpRequest对象的一个简单运用示例

    XMLHttpRequest()是一个构建HTTP请求的JavaScript对象(即构造器)。
    XMLHttpRequest()对象的用法,主要分为两个有效步骤:

    • 发送请求——这一步,完成XMLHttpRequest对象的构建,并为其设置时间监听器。
    • 处理响应——这一步,事件监听器会在服务器的响应信息到达时发出通知,然后代码就会忙于从中提取有用的信息

    发送请求 :
    1、创建一个对象,并为其设置一个能触发readystatechange事件的事件监听器

    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = callback;

    2、调用open()方法

    xhr.open(‘GET’, ‘myfile.txt’, true);

    第一个参数是http请求的类型(GET、POST、HEAD等);第二个参数是请求目标的URL(该示例请求的是与当前页面处于同一目录下的文本文件myfile.txt)。第三个参数是布尔值,该值决定了请求是否按照异步的方式进行(true表示异步请求,false表示不是异步请求)。

    3、发送请求

    xhr.send(’’); //该示例发送一个空字符串

    处理响应
    每个XHR对象中都有一个readystate属性。一旦该属性值改变就会触发readystatechange事件。该属性可能的状态中有:

    0——未初始化状态
    1——载入请求状态
    2——载入请求完成状态
    3——请求交互状态
    4——请求完成状态

    当请求的值为4时,说明服务端的响应信息已经返回,可以处理了。在callback函数中,除了确定readyState的值是4外,还要检查http请求的状态码。如果目标URL实际上不存在,就会收到一个值为404的状态码(表示未找到文件),正常情况下值为200。状态码可以通过XHR对象的statues属性来获得。
    一旦xhr.readyState值为4并且xhr.status值为200,就可以通过xhr.responseText来访问目标URL中的内容了。下面代码演示了在callback中实现用alert()方法来显示目标URL中的内容:

    function callback() {
    if (xhr.readyState < 4) {
    return;
    };
    if (xhr.status !== 200) {
    alert(‘the status code is not ok’);
    return;
    };
    alert(xhr.responseText);
    }

    • responseText:获取字符串形式的响应数据
    • responseXML:获取 XML 形式的响应数据
    • status 和 statusText:以数字和文本形式返回 HTTP 状态码
    • getAllResponseHeader():获取所有的响应报头
    • getResponseHeader():查询响应中某个字段的值
    3.从服务端接收数组的 JSON 数据
    • 如果从服务端接收的是数组的 JSON 数据,则 JSON.parse 会将其转换为 JavaScript 数组:
     <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <h2>内容是数组</h2>
    <p>内容是数组会转换为 JavaScript 数组。</p>
    
    <p id="demo"></p>
    
    <script>
    
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            myArr = JSON.parse(this.responseText);
            document.getElementById("demo").innerHTML = myArr[1];
        }
    };
    xmlhttp.open("GET", "/try/ajax/json_demo_array.txt", true);
    xmlhttp.send();
    
    </script>
    
    <p>查看服务端数据 <a href="/try/ajax/json_demo_array.txt" target="_blank">json_demo_array.txt</a></p>
    
    </body>
    </html>
     
    

    在这里插入图片描述

    在这里插入图片描述

    4.异常
    4.1 解析数据
    • JSON 不能存储 Date 对象。
      如果你需要存储 Date 对象,需要将其转换为字符串,之后再将字符串转换为 Date 对象。
     <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <h2>将字符串转换为 Date 对象。</h2>
    
    <p id="demo"></p>
    
    <script>
    
    var text = '{ "name":"Runoob", "initDate":"2013-12-14", "site":"www.runoob.com"}';
    var obj = JSON.parse(text);
    obj.initDate = new Date(obj.initDate);
    
    document.getElementById("demo").innerHTML = obj.name + "创建日期: " + obj.initDate;
    
    </script>
    
    </body>
    </html>
     
    

    在这里插入图片描述

    • 我们可以启用 JSON.parse 的第二个参数 reviver,一个转换结果的函数,对象的每个成员调用此函数。
     <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <h2>字符串转换为 Date 对象</h2>
    
    <p id="demo"></p>
    
    <script>
    
    var text = '{ "name":"Runoob", "initDate":"2013-12-14", "site":"www.runoob.com"}';
    var obj = JSON.parse(text, function (key, value) {
    	if (key == "initDate") {
    	    return new Date(value);
    	} else {
    	    return value;
    }});
    
    document.getElementById("demo").innerHTML = obj.name + "创建日期:" + obj.initDate;
    
    </script>
    
    </body>
    </html>
     
    
    4.2 解析函数
    • JSON 不允许包含函数,但你可以将函数作为字符串存储,之后再将字符串转换为函数
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <h2>字符串转换为函数</h2>
    
    <p id="demo"></p>
    
    <script>
    
    var text = '{ "name":"Runoob", "alexa":"function () {return 10000;}", "site":"www.runoob.com"}';
    var obj = JSON.parse(text);
    obj.alexa = eval("(" + obj.alexa + ")");
    
    document.getElementById("demo").innerHTML = obj.name + " Alexa 排名:" + obj.alexa(); 
    
    </script>
    
    </body>
    </html> 
     
    

    在这里插入图片描述

    • 不建议在 JSON 中使用函数。
    4.3 浏览器支持
    • 主流浏览器都支持 JSON.parse() 函数:

    Firefox 3.5
    Internet Explorer 8
    Chrome
    Opera 10
    Safari 4

    (六)JSON.stringify()

    JSON 通常用于与服务端交换数据。
    在向服务器发送数据时一般是字符串。
    我们可以使用 JSON.stringify() 方法将 JavaScript 对象转换为字符串。

    1. 语法

    JSON.stringify(value[, replacer[, space]])

    参数说明:

    • value:必需, 要转换的 JavaScript 值(通常为对象或数组)。
    • replacer:可选。用于转换结果的函数或数组。
      如果 replacer 为函数,则 JSON.stringify 将调用该函数,并传入每个成员的键和值。使用返回值而不是原始值。如果此函数返回 undefined,则排除成员。根对象的键是一个空字符串:""。
      如果 replacer 是一个数组,则仅转换该数组中具有键值的成员。成员的转换顺序与键在数组中的顺序一样。当 value 参数也为数组时,将忽略 replacer 数组。
    • space:可选,文本添加缩进、空格和换行符,如果 space 是一个数字,则返回值文本在每个级别缩进指定数目的空格,如果 space 大于 10,则文本缩进 10 个空格。space 也可以使用非数字,如:\t。
    2. JavaScript 对象转换

    例如我们向服务器发送以下数据:

    var obj = { “name”:“runoob”, “alexa”:10000, “site”:“www.runoob.com”};

    使用 JSON.stringify() 方法处理以上数据,将其转换为字符串:

    var myJSON = JSON.stringify(obj);

    myJSON 为字符串。

    我们可以将 myJSON 发送到服务器:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <h2>将 JavaScript 对象转换为 JSON 字符串</h2>
    
    <p id="demo"></p>
    
    <script>
    
    var obj = { "name":"runoob", "alexa":10000, "site":"www.runoob.com"};
    var myJSON = JSON.stringify(obj);
    document.getElementById("demo").innerHTML = myJSON;
    
    </script>
    
    </body>
    </html>
     
    

    在这里插入图片描述

    3. JavaScript 数组转换
    • 我们也可以将 JavaScript 数组转换为 JSON 字符串:

    实例
    var arr = [ “Google”, “Runoob”, “Taobao”, “Facebook” ];
    var myJSON = JSON.stringify(arr);

    myJSON 为字符串。
    我们可以将 myJSON 发送到服务器:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <h2>将 JavaScript 数组转换为 JSON 对象</h2>
    
    <p id="demo"></p>
    
    <script>
    
    var arr = [ "Google", "Runoob", "Taobao", "Facebook" ];
    var myJSON = JSON.stringify(arr);
    document.getElementById("demo").innerHTML = myJSON;
    
    </script>
    
    </body>
    </html>
     
    

    在这里插入图片描述

    4. 异常
    4.1 解析数据

    JSON 不能存储 Date 对象。
    JSON.stringify() 会将所有日期转换为字符串。

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <h2>JSON.stringify 将 Date 对象转换为字符串</h2>
    
    <p id="demo"></p>
    
    <script>
    
    var obj = { "name":"Runoob", "initDate":new Date(), "site":"www.runoob.com"};
    var myJSON = JSON.stringify(obj);
    document.getElementById("demo").innerHTML = myJSON;
    
    </script>
    
    </body>
    </html>
     
    

    在这里插入图片描述
    之后你可以再将字符串转换为 Date 对象。

    4.2 解析函数

    JSON 不允许包含函数,JSON.stringify() 会删除 JavaScript 对象的函数,包括 key 和 value。

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <h2>JSON.stringify 将删除对象中的函数</h2>
    
    <p id="demo"></p>
    
    <script>
    
    var obj = { "name":"Runoob", "alexa":function () {return 10000;}, "site":"www.runoob.com"};
    var myJSON = JSON.stringify(obj);
    document.getElementById("demo").innerHTML = myJSON;
    
    </script>
    
    </body>
    </html>
     
    

    在这里插入图片描述
    我们可以在执行 JSON.stringify() 函数前将函数转换为字符串来避免以上问题的发生:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    
    <h2>JSON.stringify 将移除对象中的函数</h2>
    
    <p>我们可以在执行 JSON.stringify() 函数前将函数转换为字符串来保留函数。</p>
    
    <p id="demo"></p>
    
    <script>
    
    var obj = { "name":"Runoob", "alexa":function () {return 10000;}, "site":"www.runoob.com"};
    obj.alexa = obj.alexa.toString();
    var myJSON = JSON.stringify(obj);
    document.getElementById("demo").innerHTML = myJSON;
    
    </script>
    
    </body>
    </html>
    

    不建议在 JSON 中使用函数。

    4.3 浏览器支持

    主流浏览器都支持 JSON.stringify() 函数:

    Firefox 3.5
    Internet Explorer 8
    Chrome
    Opera 10
    Safari 4

    (七)JSON 使用

    JSON 最常见的用法之一,是从 web 服务器上读取 JSON 数据(作为文件或作为 HttpRequest),将 JSON 数据转换为 JavaScript 对象,然后在网页中使用该数据。

    1. JSON 实例 - 来自字符串的对象

    创建包含 JSON 语法的 JavaScript 字符串:

    var txt = ‘{ “sites” : [’ +
    ‘{ “name”:“菜鸟教程” , “url”:“www.runoob.com” },’ +
    ‘{ “name”:“google” , “url”:“www.google.com” },’ +
    ‘{ “name”:“微博” , “url”:“www.weibo.com” } ]}’;

    由于 JSON 语法是 JavaScript 语法的子集,JavaScript 函数 eval() 可用于将 JSON 文本转换为 JavaScript 对象。

    eval() 函数使用的是 JavaScript 编译器,可解析 JSON 文本,然后生成 JavaScript 对象。必须把文本包围在括号中,这样才能避免语法错误:

    var obj = eval ("(" + txt + “)”);

    在网页中使用 JavaScript 对象:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
    </head>
    <body>
    <h2>JSON 字符串中创建对象</h2>
    <p>
    网站名: <span id="name"></span><br> 
    网站地址: <span id="url"></span><br> 
    </p> 
    <script>
    var txt = '{ "sites" : [' +
    '{ "name":"菜鸟教程" , "url":"www.runoob.com" },' +
    '{ "name":"google" , "url":"www.google.com" },' +
    '{ "name":"微博" , "url":"www.weibo.com" } ]}';
    
    var obj = eval ("(" + txt + ")");
    
    document.getElementById("name").innerHTML=obj.sites[0].name 
    document.getElementById("url").innerHTML=obj.sites[0].url 
    </script>
    </body>
    </html>
    
    

    在这里插入图片描述

    2. JSON 解析器

    eval() 函数可编译并执行任何 JavaScript 代码。这隐藏了一个潜在的安全问题。

    使用 JSON 解析器将 JSON 转换为 JavaScript 对象是更安全的做法。JSON 解析器只能识别 JSON 文本,而不会编译脚本。

    在浏览器中,这提供了原生的 JSON 支持,而且 JSON 解析器的速度更快。

    较新的浏览器和最新的 ECMAScript (JavaScript) 标准中均包含了原生的对 JSON 的支持。

    在这里插入图片描述
    使用eval()函数

    Js代码:
    var data="
    {
    root:
    [
    {name:‘1’,value:‘0’},
    {name:‘6101’,value:‘北京市’},
    {name:‘6102’,value:‘天津市’},
    {name:‘6103’,value:‘上海市’},
    {name:‘6104’,value:‘重庆市’},
    {name:‘6105’,value:‘渭南市’},
    {name:‘6106’,value:‘延安市’},
    {name:‘6107’,value:‘汉中市’},
    {name:‘6108’,value:‘榆林市’},
    {name:‘6109’,value:‘安康市’},
    {name:‘6110’,value:‘商洛市’}
    ]
    }";
    var dataObj=eval("("+data+")");//转换为json对象

    为什么要 eval这里要添加 “("("+data+")");//”呢?
    原因在于:eval本身的问题。 由于json是以”{}”的方式来开始以及结束的,在JS中,它会被当成一个语句块来处理,所以必须强制性的将它转换成一种表达式。
    加上圆括号的目的是迫使eval函数在处理JavaScript代码的时候强制将括号内的表达式(expression)转化为对象,而不是作为语 句(statement)来执行。举一个例子,例如对象字面量{},如若不加外层的括号,那么eval会将大括号识别为JavaScript代码块的开始 和结束标记,那么{}将会被认为是执行了一句空语句。所以下面两个执行结果是不同的:

    Js代码
    alert(eval("{}"); // return undefined
    alert(eval("({})");// return object[Object]

    对于这种写法,在JS中,可以到处看到。
    如: (function()) {}(); 做闭包操作时等。

    (八)JSONP 教程

    Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据。

    为什么我们从不同的域(网站)访问数据需要一个特殊的技术( JSONP )呢?这是因为同源策略。

    同源策略,它是由 Netscape 提出的一个著名的安全策略,现在所有支持 JavaScript 的浏览器都会使用这个策略。

    1. JSONP 应用
    1.1 服务端 JSONP 格式数据

    如客户想访问 : https://www.runoob.com/try/ajax/jsonp.php?jsoncallback=callbackFunction。

    假设客户期望返回数据:[“customername1”,“customername2”]。

    真正返回到客户端的数据显示为: callbackFunction([“customername1”,“customername2”])。

    服务端文件 jsonp.php 代码为:

    jsonp.php 文件代码
    <?php
    header('Content-type: application/json');
    //获取回调函数名
    $jsoncallback = htmlspecialchars($_REQUEST ['jsoncallback']);
    //json数据
    $json_data = '["customername1","customername2"]';
    //输出jsonp格式的数据
    echo $jsoncallback . "(" . $json_data . ")";
    ?>
    
    
    1.2 客户端实现 callbackFunction 函数
    <script type="text/javascript">
    function callbackFunction(result, methodName)
    {
        var html = '<ul>';
        for(var i = 0; i < result.length; i++)
        {
            html += '<li>' + result[i] + '</li>';
        }
        html += '</ul>';
        document.getElementById('divCustomers').innerHTML = html;
    }
    </script>
    

    页面展示:

    <div id="divCustomers"></div>
    

    客户端页面完整代码:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>JSONP 实例</title>
    </head>
    <body>
    <div id="divCustomers"></div>
    <script type="text/javascript">
    function callbackFunction(result, methodName)
    {
        var html = '<ul>';
        for(var i = 0; i < result.length; i++)
        {
            html += '<li>' + result[i] + '</li>';
        }
        html += '</ul>';
        document.getElementById('divCustomers').innerHTML = html;
    }
    </script>
    <script type="text/javascript" src="https://www.runoob.com/try/ajax/jsonp.php?jsoncallback=callbackFunction"></script>
    </body>
    </html>
    
    2. jQuery 使用 JSONP

    以上代码可以使用 jQuery 代码实例:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>JSONP 实例</title>
        <script src="https://cdn.static.runoob.com/libs/jquery/1.8.3/jquery.js"></script>    
    </head>
    <body>
    <div id="divCustomers"></div>
    <script>
    $.getJSON("https://www.runoob.com/try/ajax/jsonp.php?jsoncallback=?", function(data) {
        
        var html = '<ul>';
        for(var i = 0; i < data.length; i++)
        {
            html += '<li>' + data[i] + '</li>';
        }
        html += '</ul>';
        
        $('#divCustomers').html(html); 
    });
    </script>
    </body>
    </html>
    
    展开全文
  • 对接接口需要发送json数据,我想按照接口文档上的顺序,输出json,所以才了这篇文章 刚开始用JSONObject.toJSON(),里面直接放对象,dto里设置排序也不起作用,尝试各种方法后,所以先转json字符串,然后在转成...


    对接接口需要发送json数据,我想按照接口文档上的顺序,输出json,所以才有了这篇文章
    刚开始用JSONObject.toJSON(),里面直接放对象,dto里设置排序也不起作用,尝试各种方法后,所以先转json字符串,然后在转成对象时加上Feature.OrderedField,保证转成对象后顺序一致

    本文中JSONObject用的版本是fastjson 1.2.68

    • DTO中加上@JSONType注解,orders里放的是json字符串的排序,@JSONField(format="yyyy-MM-dd HH:mm:ss")这个是因为有字段是日期类型的,进行处理。此处只设置一个DTO,另一个类似
    @Data
    @JSONType(orders={"serviceTime","zoning"})
    public class EvaluatePersonDTO implements Serializable {
        //服务时间
        @JSONField(format="yyyy-MM-dd HH:mm:ss")
        private Date serviceTime;
    
        //区划
        private  String zoning;
    } 
    • 需要调用的类中,json对象放多个dto时,顺序会变化,加上设置JSONObject(true),保证出来对象顺序正常,
    JSONObject applicationJson = new JSONObject(true);
    
    EvaluatePersonDTO evaluatePersonDTO = new EvaluatePersonDTO();  //人员对象
    evaluatePersonDTO.setBprArea("640101000000");                   //被评人所属区划
    evaluatePersonDTO.setBprDept("研发部");                        //被评人所属部门
    //        
    evaluatePersonDTO.setBprDept(sysOffice.getName());          //被评人所属部门--暂时没查询到
    evaluatePersonDTO.setBprName(currentUser.getLoginName());                //被评人员姓名
           
    evaluatePersonDTO.setBprName(sysUser.getName());                       //被评人员姓名
    evaluatePersonDTO.setIsApplication("0");    //是否关联办件
    evaluatePersonDTO.setPjqd("");              //评价渠道
    evaluatePersonDTO.setServiceTime(parseDate(DateUtils.getDateTime()));          //服务时间
    evaluatePersonDTO.setZoning("640101000000");                    //区划
    
    EvaluateWindowDTO evaluateWindowDTO = new EvaluateWindowDTO();  //窗口对象
    evaluateWindowDTO.setCkDept("银川政务大厅");               //窗口所属部门
           
    evaluateWindowDTO.setCkDept(sysOffice.getName());               //窗口所属部门
    evaluateWindowDTO.setCkNumber("2");                             //窗口号
    evaluateWindowDTO.setIsApplication("0");                        //是否关联办件
    evaluateWindowDTO.setPjqd("");                                  //评价渠道
    evaluateWindowDTO.setZoning("640101000000");                    //行政区划
    
    applicationJson.put("personDTO",JSONObject.parseObject(JSON.toJSONString(evaluatePersonDTO), Feature.OrderedField));
    applicationJson.put("windowDTO",JSONObject.parseObject(JSON.toJSONString(evaluateWindowDTO), Feature.OrderedField));
    
    HttpHeaders headers = new HttpHeaders();
    MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
    headers.setContentType(type);
    headers.add("Accept", MediaType.APPLICATION_JSON.toString());
    HttpEntity<String> formEntity = new HttpEntity<String>(applicationJson.toString(), headers);
    String s= restTemplate.postForEntity(applicationConfig.goodAndBadEvaluatePath,formEntity,String.class).getBody();

     

    最终结果,左侧是运行显示的部分json数据,右侧是接口文档部分字段,主要关注personDTO和windowDTO对象就行

    展开全文
  • 按照对象属性顺序传递json

    千次阅读 2018-12-07 14:24:04
    由于前后台数据传递都是以json形式互相通信,所以就涉及json传递数据的属性排序问题。以下测试使用阿里的fastjson。 首先使用JSONObject的put方法,一开始我以为是按照字符顺序排序的,但是经过测试发现并不是这样 ...

    上午刚好碰到这个问题,简单的查了一下,然后记录一下。

    参考文章

    由于前后台数据传递都是以json形式互相通信,所以就涉及json传递数据的属性排序问题。以下测试使用阿里的fastjson

    首先使用JSONObject的put方法,一开始我以为是按照字符顺序排序的,但是经过测试发现并不是这样
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    根据测试结果可以看出,应该是内部实现的时候,排序方法就有一定的问题。

    当我们在controller中直接返回LinkedHashMap的时候,得到的属性顺序就是按照map的put时的顺序,比如:
    在这里插入图片描述

    在这里插入图片描述

    因此,当涉及到使用属性顺序的情况时,我们就需要尽量使用这种直接传递对象的形式。

    那么能否让json串中的数据按照我们想要的格式进行排序呢?

    我们通常会将对象转化为json串,然后再进行传递,所以我们可以在对象中对其属性进行排序,使用@JSONField(ordinal = n),即可返回按照设定顺序的json串,如下
    在这里插入图片描述

    在这里插入图片描述

    当我们不使用这个注解的时候,就会使用JSONObject的默认排序规则,顺序就会打乱。
    如下
    在这里插入图片描述
    在这里插入图片描述

    分析

    这时我们分析一下为什么会出现json的属性排序打乱这个问题。

    首先在JSONObject的构造函数,我们可以看到,默认情况下JSONObject中的map使用的是HashMap
    在这里插入图片描述

    所以问题就转移为,为什么HashMap会出现次序被打乱的情况。

    首先,根据我的测试,在jdk1.8中,使用HashMap进行测试。
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    通过这几张图就能发现貌似有什么不对。

    那么,接下来我们就需要寻根溯源,一探HashMap的源码。。。


    经过我们对HashMap源码的探究,大概发现了HashMap中值的排序规则,主要就是依据HashCode来进行相关的排序。
    而我们又知道HashMap中的HashCode是这样计算的。

    static final int hash(Object key) {
            int h;
            return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
        }
    

    也就是对key值取hashCode,并与它的右移16位得到的值进行异或操作。

    接着我进行了一下测试,发现确实如此。
    在这里插入图片描述

    然后再和容量进行hash操作,就能得到在HashMap中的hash值。我们的HashMap的容量为默认值16
    "aaa"对应的hash为10111100001000000,容量1111(16-1),经过与操作得到的hash为0000
    同理,"bbb"为0011;"ccc"为0010;"ddd"为0101;"eee"为0100
    根据这几个hash值得排序得到顺序为"aaa","ccc","bbb","eee","ddd",和我们在map得toString方法得到的顺序一致。

    但是我们之前测试的"aa",“bb”…这个好像就不一样,当我们数据为9个的时候,貌似还有一个顺序,但是当数据为10个了,就会发现突然乱序了。

    经过计算,我们发现"aa",“bb”…这些key值的最终hash为0000,所以,它们都映射到hash tab中的一个元素上了,也就是一个链表,我们在HashMap源码的研究中发现,当数据量达到一个阈值时,就会将链表变为红黑树,那么,为了解决这个问题,我们接下来就需要了解红黑树了。


    红黑树的基础知识

    关于HashMap中的红黑树源码的解读,这里看到一篇很好的文章,所以我就不重复劳动了,而且看源码好费脑子和时间啊?
    http://www.cnblogs.com/graywind/p/9471756.html


    这里补一个插曲,因为我们在看HashMap源码的时候,有追踪到hashcode()方法,虽然不同的类都有自己的hashcode()方法实现,但是最基础的object类的hashcode()方法确是一个比较特殊的存在。

    public native int hashCode();
    

    从而引出了native关键字,以及相关外部hashcode()源码是如何实现等知识,这里贴一些我看到的比较好的文章。

    关于native关键字:
    https://www.cnblogs.com/Qian123/p/5702574.html
    https://blog.csdn.net/Aphysia/article/details/80593654

    关于hashcode()源码的解析:
    http://www.cnblogs.com/dolphin0520/p/3681042.html


    最后,让我们为整个问题划一个圆满的句号吧。

    回顾我们上面的解读,仅剩下最后一个问题,就是当

    Map map = new HashMap();
            map.put("aa", 10);
            map.put("bb", 9);
            map.put("cc", 8);
            map.put("dd", 7);
            map.put("ee", 6);
            map.put("ff", 5);
            map.put("gg", 4);
            map.put("hh", 3);
            map.put("ii", 2);
            map.put("jj", 1);
    
            System.out.println(map);
    

    在这里插入图片描述
    打印出来的顺序变得很混乱,我们知道了在table.size()为16的时候,这些值最后映射的bin为0。(1111与每个key的hash()结果进行与操作)

    而我们在看putVal源码的时候,发现当bin数量达到一定值时,就会执行treeifyBin,也就是将链表进行红黑树化。为此,我还花费了很长时间去学习红黑树的知识,并且看了HashMap中红黑树的源码。

    但是! 我发现结果并不是我想的那样,我们上面的例子最后并没有红黑树化。下面我们来分析为什么没有红黑树化。

    我们先看putVal()方法,我只截取其中的关键部分,也就是每次进行值插入时的代码块。

    				for (int binCount = 0; ; ++binCount) {
                        if ((e = p.next) == null) {
                            p.next = newNode(hash, key, value, null);
                            if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                                treeifyBin(tab, hash);
                            break;
                        }
                        if (e.hash == hash &&
                            ((k = e.key) == key || (key != null && key.equals(k))))
                            break;
                        p = e;
                    }
    

    这部分代码就是统计bin链表中元素个数,并是否进行红黑树化的代码块。判断条件为:

    if (binCount >= TREEIFY_THRESHOLD - 1)
    

    但是这个条件只有在我们插入第9个值时才会进入,你可以手动模拟一下,接着就是执行treeifyBin这个方法,所以我们进入这个方法看一下。

    final void treeifyBin(Node<K,V>[] tab, int hash) {
            int n, index; Node<K,V> e;
            if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
                resize();
            else if ((e = tab[index = (n - 1) & hash]) != null) {
                TreeNode<K,V> hd = null, tl = null;
                do {
                    TreeNode<K,V> p = replacementTreeNode(e, null);
                    if (tl == null)
                        hd = p;
                    else {
                        p.prev = tl;
                        tl.next = p;
                    }
                    tl = p;
                } while ((e = e.next) != null);
                if ((tab[index] = hd) != null)
                    hd.treeify(tab);
            }
        }
    

    看到这时,我人晕了。首先就有这个条件:

    		// MIN_TREEIFY_CAPACITY = 64
    		if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
                resize();
    

    而我们table初始长度为16啊,所以这里对table进行了一次扩容,但是并没有真正的红黑树化。当我们插入第10个值时,又进行了一次扩容,之后再插入值时,table结构已经发生了变化,所以也并没有红黑树化,直到满足条件的时候才会真正的红黑树化。

    那么我们来分别分析插入第9个值和插入第10个值时,打印结果为什么会不同。

    插入9个值结果
    在这里插入图片描述

    插入10个值结果
    在这里插入图片描述

    我们再看一下这些hash值的二进制:
    aa: 1100 0010 0000
    bb: 1100 0100 0000
    cc: 1100 0110 0000
    dd: 1100 1000 0000
    ee: 1100 1010 0000
    ff: 1100 1100 0000
    gg: 1100 1110 0000
    hh: 1101 0000 0000
    ii: 1101 0010 0000
    jj: 1101 0100 0000

    然后插入第9个值,也就是"ii"的时候,进行了第一次扩容,此时table.size()为32,11111与上面hash值进行&操作。此时所有还是都为0,链表中有9个值,所以打印出来的结果还是按照hash排序的
    插入第10个值,也就是"jj"时,进行了第二次扩容,此时size为64,111111与上面hash值进行&操作。这时得到的值为两组,分别为032,然后我们就会发现,0组的值有:bb,dd,ff,hh,jj;32组的有:aa,cc,ee,gg,ii。

    至此,水落石出,我们终于查清,为什么会这样了。

    一个小问题引出的惊天大案,至此完美落幕

    展开全文
  • 问题复现: 建表 CREATE TABLE `test_json` ( `id` int(11) NOT NULL AUTO_INCREMENT, ...添加json数据 { "a": "aaaaa", "bbbb": "bb", "ccc": "ccc" } 查询更新后数据顺序发生变化 UPDATE test_json ..
    1. 问题复现:
      建表

      CREATE TABLE `test_json` (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `json` json DEFAULT NULL,
        PRIMARY KEY (`id`)
      ) ENGINE=InnoDB AUTO_INCREMENT=1;
      

      添加json数据

      {
        "a": "aaaaa",
        "bbbb": "bb",
        "ccc": "ccc"
      }
      

      查询更新后数据顺序发生变化

      UPDATE test_json SET json ='{"a": "aaaaa","bbbb":"bb","ccc":"ccc"}' WHERE ID = 1;
      SELECT json from test_json WHERE ID = 1
      

      在这里插入图片描述

    2. 问题解决
      资料:
      https://stackoverflow.com/questions/48382457/mysql-json-column-change-array-order-after-saving
      在这里插入图片描述
      结论:

      老老实实用text结构的类型吧,mysql在存储json时按照key的字段长度做了排序,以便获得更好的存储性能,目前不支持顺序json,所以还是自己第三方工具序列化下吧

      mysql本身是关系型数据库,对文档类型的数据还是用nosql吧比如MongoDB

    展开全文
  • 由于使用DataTable进行数据渲染,调用接口获取的Json数据中对象的属性不是原来的顺序了,原因是在进行Json格式化的时候,使用JsonUntils进行转json,内部使用的map是无序的。 需要的数据格式示例: [ { "userName":...
  • json 按照输入顺序输出结果

    千次阅读 2017-06-06 21:13:36
    import json from collections import OrderedDict json_data = '{"test": 1, "test2": 2, "test3":2}' data = json.loads(json_data, object_pairs_hook=OrderedDict) ...
  • JavaBean转换为Json指定数据格式 ...解决方法:在JavaBean的属性上添加注解 @JSONField(), ordinal:为指定序列化顺序 name:指定序列化后Json数据格式key的名称。 Demo : @JSONField(ordinal = 1, nam...
  • 最近在做项目的时候,我碰到了一个问题,使用json传递报文的时候怎么保存报文的顺序?比如下面一段报文: { "ec": { "request": { "header": { "actiontype": "00", "currenttime": "1586003427105" ...
  • 今天在工作中遇到一个问题,一个服务提供接口数据,且数据为字符串,字符串中Map结构也保持有顺序,另一个接口,获取时需要保留原有的map顺序,且存放到linkHashMap中,最终放入缓存中进行使用。 本例中使用...
  • 使用NlohmannJsonJSON保留插入顺序

    千次阅读 2020-01-05 15:59:37
    使用NlohmannJsonJSON保留插入顺序
  • JS 遍历 json对象的顺序错乱

    千次阅读 2017-07-25 18:40:00
    在js中 使用 for(var a in b) 之类遍历的时候 ...如果 b 是json对象不能保证按照原顺序遍历。 若想按照顺序遍历需要把 b 转换为 array。 顶 转载于:https://www.cnblogs.com/gongchixin/articles/7235843.html...
  • 批量xml格式文件按字段顺序json文件
  • json字符串序列化后如何保持顺序不变 使用阿里巴巴的fastjson对json字符串进行序列化,序列化之后发现顺序发生了改变,导致之后业务出现问题。 解决方法: LinkedHashMap&amp;lt;String, Object&amp;gt; ...
  • JSON.toJSONString过程中出现实体类的属性与转换之前的顺序不一致 public static void main(String[] args) { Person person = new Person(); person.setName("Tom"); person.setAge(20); person.setGende...
  • json转xml时的顺序问题

    2017-04-27 02:07:45
    json转xml时,元素会按照字符串的自然排序来添加到xml中,什么办法解决?
  • //把字符串原生转换为json对象,如果不加第二个参数OrderedField,会无序 JSONObject jsonObject = JSON.parseObject(json, Feature.OrderedField);
  • String字符串转Json 方式一:org.json 程序包: <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20171018</version> </...
  • json 数据的添加修改

    千次阅读 2017-07-20 18:21:32
    json的数据,添加,删除,排序
  • js 把对象按照属性名的字母顺序进行排列 var obj = {name: “zhangsan”, age: 8, ace: 5, nbme: “lisi”};//要排序的对象 function objKeySort(obj) {//排序的函数 var newkey = Object.keys(obj).sort();  //先...
  • JSON.awk 用awk编写的实用JSON解析器。 介绍 JSON.awk是一个独立的单文件程序,没有任何外部依赖关系。 它类似于 ,这是用Bash编写的JSON解析器-于2013-03-13检索以构成JSON.awk的... JSON.awk通常在Linux上按此顺序
  • // 在创建JSON对象时传入LinkedHashMap。 // 组装行数据输出 JSONObject row = new JSONObject(new LinkedHashMap<>()); 如下图:传入有序LinkedHashMap后会使用转入的Map存储元素. public ...
  • 其中传的参数data中前面几个json数据是固定的,最后需要加一个签名,该签名是对前面的json数据字符串化后,首尾拼接上screct字符串,再做md5处理(32位大写),再将该签名添加到之前的json中作为post参数传递过去。...
  • 这篇文章主要介绍了json格式数据的添加,删除及排序方法,结合实例形式分析了针对一维数组与二维数组的json格式数据进行增加、删除与排序的实现技巧,需要的朋友可以参考下 ...js数据格式和json数据格式,各
  • 按字母顺序对所选JSON对象中的键进行排序。 请谨慎使用-我已尝试确保它不会使您的JSON无效。 但是,由于必须解析>排序>字符串化,因此可能会丢失某些内容。 对于纯JSON应该没问题。 安装 通过VSCode扩展安装 ...
  • 对象在转json字符串的时候,输出的字符串顺序和...这个是对model的属性添加了@JsonField注解之后的效果。输出的json字符串和model里面的属性顺序一致了。 2次测试使用的都是这个model,只是后面对这个model对属...
  • 示例json: { &quot;name&quot;: &quot;御道风云&quot;, &quot;url&quot;: &quot;http://www.yudaofengyun.com&quot;, &quot;age&quot;: 16, &quot;sex&...
  • 在遍历FacetField中,以为可以按照取的顺序添加json中,然而在把json传递给前端页面时发现原本排好序的顺序乱了。问题:问题出在json格式为:{字段:{字段内容:计数}...};原因:找了大量文章发现,json内的...
  • 使用fastjson将对象转换成json字符串 JSON.toJSONString(tableResult1) 这个tableResult1对象在转换之前顺序没有...第二种:是在实体类属性上加注解(多少字段加多少按照从1到大的顺序加上)@JSONField(ordinal = 1..

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 102,159
精华内容 40,863
关键字:

有添加顺序的json