Ajax与Python操作JSON数据

JSON的基本概念

基本概念

JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)

JSON 是轻量级的文本数据交换格式

JSON 独立于语言 *

JSON 具有自我描述性,更易理解

JSON与Python

json数据类型和python数据类型的对比:

  object和python的dict类型是差不多的,但是要求里面必须是双引号,string和list、tuple等也是一样的,都是双引号。

  但是要注意:python中的datetime等时间日期类型是不能进行json序列化的,因为json没有对应的格式,上面的这几种数据类型虽然进行json.dumps序列化之后都是个字符串,但是也是有格式的!

  前端ajax拿到后端返回的一个python的json模块序列化之后的一个json字符串,那么js通过自己的json接口,将接受到的json字符串来反序列化为js自己语言能够识别的数据类型,然后再进行操作。 

  相当于我有一个json方法,你有一个json方法,你给我发数据必须是json字符串的格式,那么你就需要将你的数据类型序列化为json的字符串,那么序列化的时候,就把你的数据序列化为了符合json标准的字符串,然后我接收到这个字符串之后,我通过我的json方法,将数据转换为我的语言支持的数据类型。在进行反序列化的时候,如果你的字符串不符合json的格式,那么反序列化的时候就会报错,所以只要你是通过json序列化成的字符串,都是能够json反序列化的,因为json序列化的时候,就把你的数据改为了符合json标准的字符串形式,例如:里面的单引号,序列化后变成了双引号。

   合格的json对象:

["one", "two", "three"]
{ "one": 1, "two": 2, "three": 3 } #这就是一个json的object类型,符合json的标准格式,就可以通过dumps来进行序列化
{"names": ["whw", "naruto"] }
[ { "name": "whw"}, {"name": "naruto"} ] 

  不合格的json对象:

{ name: "whw", 'age': 22 }  #属性名必须使用双引号
[32, 64, 128, 0xFFF] #不能使用十六进制值
{ "name": "whw", "age": undefined }  #不能使用undefined
{ "name": "whw",
  "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
  "getName":  function() {return this.name;}  #不能使用函数和日期对象
}

  普通字符串和json字符串,在进行序列化的时候的区别

import json
# s = "{'name':'whw','age':18}" #普通字符串,每加引号的没问题,加了引号的,必须是双引号才能使用json.loads()。
s = '{"name":"whw","age":18}'   #json字符串,里面必须是双引号
ret = json.loads(s)
print(ret)
print(ret['name'])

JSON与JS

js的stringify与parse方法

JavaScript中关于JSON对象和字符串转换的两个方法:

JSON.parse()

用于将一个 JSON 字符串转换为 JavaScript 对象

JSON.parse('{"name":"whw"}');  //正确
JSON.parse('{name:"whw"}') ;   //错误
JSON.parse('[18,undefined]') ; //错误

JSON.stringify()

用于将 JavaScript 值转换为 JSON 字符串

JSON.stringify({"name":"whw"})

JSON与XML

JSON 格式于2001年由 Douglas Crockford 提出,目的就是取代繁琐笨重的 XML 格式。

JSON 格式有两个显著的优点:书写简单,一目了然;符合 JavaScript 原生语法,可以由解释引擎直接处理,不用另外添加解析代码。所以,JSON迅速被接受,已经成为各大网站交换数据的标准格式,并被写入ECMAScript 5,成为标准的一部分。

XML和JSON都使用结构化方法来标记数据,下面来做一个简单的比较。

用XML与JSON分别表示中国部分省市数据如下:

<?xml version="1.0" encoding="utf-8"?>
<country>
    <name>中国</name>
    <province>
        <name>黑龙江</name>
        <cities>
            <city>哈尔滨</city>
            <city>大庆</city>
        </cities>
    </province>
    <province>
        <name>广东</name>
        <cities>
            <city>广州</city>
            <city>深圳</city>
            <city>珠海</city>
        </cities>
    </province>
    <province>
        <name>台湾</name>
        <cities>
            <city>台北</city>
            <city>高雄</city>
        </cities>
    </province>
    <province>
        <name>新疆</name>
        <cities>
            <city>乌鲁木齐</city>
        </cities>
    </province>
</country>
XML数据
{
    "name": "中国",
    "province": [{
        "name": "黑龙江",
        "cities": {
            "city": ["哈尔滨", "大庆"]
        }
    }, {
        "name": "广东",
        "cities": {
            "city": ["广州", "深圳", "珠海"]
        }
    }, {
        "name": "台湾",
        "cities": {
            "city": ["台北", "高雄"]
        }
    }, {
        "name": "新疆",
        "cities": {
            "city": ["乌鲁木齐"]
        }
    }]
}
JSON数据

由上面的两段代码可以看出,JSON 简单的语法格式和清晰的层次结构明显要比 XML 容易阅读,并且在数据交换方面,由于 JSON 所使用的字符要比 XML 少得多,可以大大得节约传输数据所占用的带宽。 

Ajax和Python后台服务端的数据交互时的序列化问题

  当我们在后台给ajax的回调函数回复的不是一个字符串,而是其他数据类型的时候,需要我们将数据转换为json字符串进行发送,这样好配合js进行json字符串的处理,不然发送或者接受的是普通字符串的话,没办法处理成原来的数据类型。

在后台我们有三种方法去解决前后端数据在交互时序列化的问题:

方法一

后台HttpReaponse前将前端需要的数据序列化成JSON格式的数据;ajax的回调函数接收这个JSON格式的数据后再进行JS的反序列化拿到自定义对象去处理。

这种方式相对来说比较麻烦,因为需要前后端都要进行序列化与反序列化的操作。

方法二

后台HttpReaponse前将前端需要的数据序列化成JSON格式的数据,然后在提交数据的时候把自己的content_type参数设置成‘application/json’就可以了。

HttpResponse(json.dumps({'name';'chao'}),content_type='application/json')

利用这种方式,前端ajax的回调函数收到的就是一个自定义对象,不用进行反序列化操作了~

方法三(常用)

利用django内置的JsonResponse方法返回。

from django.http import JsonResponse

...

return JsonResponse({'name';'whw'})

其实这种方法是前两种方法的结合~

但是需要注意的一点是:在默认情况下JsonResponse里面的内容必须是一个字典~如果我们想把一个列表通过JsonResponse方法返回给前端的话,需要设置一个参数就好了:

from django.http import JsonResponse

...

return JsonResponse([11,22,33],safe=False)

事实上,这种方式更受欢迎~因为前端工程师非常喜欢数组类型的数据,拿到后直接进行遍历就可以了~~好吧,还是看实际情况来讲把。

前端ajax传参给后台时需要注意的问题:

data参数中的键值对,如果值值不为字符串,需要将其转换成字符串类型:

$("#b1").on("click", function () {
    $.ajax({
      url:"/ajax_add/",
      type:"GET",
      data:{"i1":$("#i1").val(),"i2":$("#i2").val(),"hehe": JSON.stringify([1, 2, 3])},//这里需要将数组序列化成JSON字符串
      success:function (data) {
        $("#i3").val(data);
      }
    })
  })

不能直接进行序列化数据类型的特殊处理

上面关于“json数据类型和python数据类型的对比”那张图显示了两种语言数据类型的对应关系。这也意味着不是所有的Python数据类型都可以进行序列化操作的!

实际中我见到不能直接序列化的Python数据类型是Decimal与Date跟Datetime数据类型。

其实,让它们可序列化的基本思路就是将这几种数据类型的数据转换成Python的str类型的数据:

Decimal数据类型的处理

现在遇到的Decimal数据类型的数据都是我从数据库中得到的,它是不可以直接进行序列化操作的,需要将其转换成str,再进行序列化操作:

这里的d一开始是Decimal类型的数据

import decimal
d = str(decimal.Decimal(d).quantize(decimal.Decimal('0.00')))

Datetime与Date类型数据的处理

Python内置的datetime模块有strftime方法可以为我们将时间类型转换成字符串类型的数据:

这里的t一开始是datetime类型的数据

from datetime import datetime
t = datetime.strftime(t,'%Y-%m-%d')

对于这两种类型的数据有位大佬写了一个类进行了统一处理,这里直接上大佬的代码:

import json
from datetime import datetime
from datetime import date

#对含有日期格式数据的json数据进行转换
class JsonCustomEncoder(json.JSONEncoder):
    def default(self, field):
        if isinstance(field,datetime):
            return field.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(field,date):
            return field.strftime('%Y-%m-%d')
        else:
            return json.JSONEncoder.default(self,field)


d1 = datetime.now()

dd = json.dumps(d1,cls=JsonCustomEncoder)
print(dd)

  关于datetime类型的数据的处理第一种方式我感觉比较常用,因为实际中我们要返回的字典不仅仅只有datetime还有其他类型的数据,需要用第一种方式去单独处理每个datetime数据;如果只有datetime类型的数据需要返回的化可以用第二种方式~

 

posted on 2019-05-30 17:24  江湖乄夜雨  阅读(3582)  评论(0编辑  收藏  举报