Python解析JSON

什么是JSON

JSON(JavaScript Object Notation)是一种轻量级的数据交换语言,以文字为基础,且易于让人阅读。JSON是Javascript的一个子集,但JSON是独立于语言的文本格式,并且采用了类似于C语言家族的一些习惯。

  • JSON 表示 JavaScript 对象表示法(JavaScript Object Notation)
  • 这个格式由 Douglas Crockford 提出
  • 被设计用于可读的数据交换
  • 它是从 JavaScript 脚本语言中演变而来
  • 文件名扩展是 .json
  • JSON 的网络媒体类型是 application/json
  • 统一标示符类型(Uniform Type Identifier)是 public.json

JSON的特点和使用范围

使用范围:

  • 用于编写基于 JavaScript 应用程序,包括浏览器扩展和网站
  • JSON 格式可以用于通过网络连接序列化和传输结构化数据
  • 主要用于在服务器和 Web 应用程序之间传输数据
  • Web 服务和 APIs 可以使用 JSON 格式提供公用数据
  • 还可以用于现代编程语言中

特点:

  • JSON 容易阅读和编写
  • 它是一种轻量级的基于文本的交换格式
  • 语言无关

与XML的比较

JSON与XML最大的不同在于XML是一个完整的标记语言,而JSON不是。这使得XML在程序判读上需要比较多的功夫。主要的原因在于XML的设计理念与JSON不同。XML利用标记语言的特性提供了绝佳的延展性(如XPath),在数据存储,扩展及高级检索方面具备对JSON的优势,而JSON则由于比XML更加小巧,以及浏览器的内建快速解析支持,使得其更适用于网络数据传输领域

JSON语法

JSON 语法是 JavaScript 对象表示法语法的子集

  • 数据在名称/值对中
  • 数据由逗号分隔
  • 花括号保存对象
  • 方括号保存数组

JSON 名称/值对

JSON 数据的书写格式是:名称/值对。 名称/值对包括字段名称(在双引号中),后面写一个冒号,然后是值:

“firstName” : “John”

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

firstName = “John”

JSON 值

JSON 值可以是: 数字(整数或浮点数) 字符串(在双引号中) 逻辑值(true 或 false) 数组(在方括号中) 对象(在花括号中) null

JSON 对象

JSON 对象在花括号中书写: 对象可以包含多个名称/值对:

{ “firstName”:”John” , “lastName”:”Doe” }

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

firstName = “John” lastName = “Doe”

JSON 数组

JSON 数组在方括号中书写: 数组可包含多个对象:

{ “employees”: [ { “firstName”:”John” , “lastName”:”Doe” }, { “firstName”:”Anna” , “lastName”:”Smith” }, { “firstName”:”Peter” , “lastName”:”Jones” } ]

}

在上面的例子中,对象 “employees” 是包含三个对象的数组。每个对象代表一条关于某人(有姓和名)的记录。

JSON示例

书籍数据有语言和版本信息,下面的例子展示了使用 JSON 存储书籍信息:

{
    "book": [
        {
            "id":"01",
            "language": "Java",
            "edition": "third",
            "author": "Herbert Schildt"
        },
        {
            "id":"07",
            "language": "C++",
            "edition": "second"
            "author": "E.Balagurusamy"
    }]
}

python解析JSON

解析基本数据

python原始类型—>JSON类型的转换关系如下:

python类型

JSON类型

dict

object

list,tuple

array

str,unicode

string

int,long,float

number

True

true

Flase

false

None

null

Python自带的json模块可以实现对JSON数据的解析:

API文档参考:HERE

主要使用的是其中的两个函数: json.dumps() 和 json.loads()

json.dumps()负责将python数据类型转换为JSON数据类型(Encoding) json.loads()负责将JSON数据类型转换为python数据类型(Decoding)

下面看一个简单的例子:

In [44]: import json

In [45]: data =[{'a':'AB','b':(2,5),'c':[4,6,7],'d':13.4}] ## python数据类型

In [46]: data_json = json.dump
json.dump   json.dumps  

In [46]: data_json = json.dumps(data)

In [47]: print data_json
[{"a": "AB", "c": [4, 6, 7], "b": [2, 5], "d": 13.4}]  ##JSON数据类型

上面可以看到,dumps将tuple转换为数组,将’AB’转换为”AB”

In [48]: json_data = {
   "book":[
        {
            "id":"01",
            "language": "Java",
            "edition": "third",
            "author": "Herbert Schildt"
        },
        {
            "id":"07",
            "language": "C++",
            "edition": "second",
            "author": "E.Balagurusamy"
         }
    ]
}

In [49]: python_data = json.loads(json_data)  ##Decode

In [50]: print python_data
{u'book': [{u'edition': u'third', u'id': u'01', u'language': u'Java', u'author': u'Herbert Schildt'}, {u'edition': u'second', u'id': u'07', u'language': u'C++', u'author': u'E.Balagurusamy'}]}

JSON数据类型—>python类型的转换关系如下:

JSON类型

python类型

object

dict

array

list

string

unicode

number(int)

int,long

number(real)

float

true

True

false

False

null

None

编码后的JSON字符串虽然结构紧凑,但是’:’后面跟的还有空格,对于web传输是不必要的,并且没有indent使得我们看起来不方便 可以在编码json.dumps()时指定一些参数,实现我们的需求

<1> sort_key

In [68]: data = [ { 'a':'A', 'b':(2, 4), 'c':3.0 } ]

In [69]: unsorted = json.dumps(data)

In [70]: print 'JSON:', json.dumps(data)
JSON: [{"a": "A", "c": 3.0, "b": [2, 4]}]

In [71]: print 'SORT:', json.dumps(data, sort_keys=True) ## 指定key排序
SORT: [{"a": "A", "b": [2, 4], "c": 3.0}]

<2> indent

In [73]: data = [ { 'a':'A', 'b':(2, 4), 'c':3.0 } ]

In [74]: print 'NORMAL:', json.dumps(data, sort_keys=True)
NORMAL: [{"a": "A", "b": [2, 4], "c": 3.0}]

In [75]: print 'INDENT:', json.dumps(data, sort_keys=True, indent=2)  ## 加入缩进,输出更加易读
INDENT: [
  {
    "a": "A", 
    "b": [
      2, 
      4
    ], 
    "c": 3.0
  }
]

<3>separators

In [76]: data = [ { 'a':'A', 'b':(2, 4), 'c':3.0 } ]

In [77]: print 'DATA:', repr(data)
DATA: [{'a': 'A', 'c': 3.0, 'b': (2, 4)}]

In [78]: print 'repr(data)             :', len(repr(data))
repr(data)             : 35

In [79]: print 'dumps(data)            :', len(json.dumps(data))
dumps(data)            : 35

In [80]: print 'dumps(data, indent=2)  :', len(json.dumps(data, indent=2))
dumps(data, indent=2)  : 76   ## 加入indent是76个字符长度

In [81]: print 'dumps(data, separators):', len(json.dumps(data, separators=(',',':')))
dumps(data, separators): 29   ## 去除','和':'之后的空格,只有29个字符,便于web传输

JSON字符串写入文件流

上面的都是在内存中直接进行的处理,如果对于大的数据显然是不可能的,需要进行文件操作,下面做个演示:

import json
import tempfile

data = [ { 'a':'A', 'b':(2, 4), 'c':3.0 } ]

##tempfile的作用是创建个临时文件,之后会被自动删除,NamedTemporaryFile表示此临时文件可以获得文件名(f.name)
f = tempfile.NamedTemporaryFile(mode='w+')   

##写入encode数据
json.dump(data, f)
f.flush()

##decode数据
with open(f.name, 'r')  as p:
    print p.read()   

结果是: [{“a”: “A”, “c”: 3.0, “b”: [2, 4]}]

解析自定义数据

这个部分我就不写了,推荐个好的博客,大家看这个就行了,廖雪峰的博客

写的很不错,大家看看应该没什么问题

解析中文的问题

loads方法如果传入的字符串的编码不是UTF-8的话,需要用encoding指定字符编码

示例:

import json

js = json.loads('{"insun": "泰囧 / 人在囧途2 / Lost in Thailand "}')

print json.dumps(js)  ##不指定编码的
{"insun": "\u6cf0\u56e7 / \u4eba\u5728\u56e7\u90142 / Lost in Thailand "}

print json.dumps(js,ensure_ascii=False)  ##正确解析
{"insun": "泰囧 / 人在囧途2 / Lost in Thailand "}

同样的如果是GB2312编码的直接指定为GB2312就行了

dataDict = json.loads(dataJsonStr, encoding='GB2312')

如果要解析的字符串,本身的编码类型,不是基于ASCII的,那么,调用json.loads之前,需要先将对应字符串,转换为Unicode类型 还是以上述的: dataDict = json.loads(dataJsonStr, encoding=’GB2312’); 为例,比如我本身 dataJsonStr 是GB2312的字符,但是其中又包含了的一些日文字符,此时,json.loads还是会出错,因为此处的 dataJsonStr 不是以ASCII为基础的字符编码,所以,需要先去将dataJsonStr转换为Unicode,然后再调用 json.loads

dataJsonStrUni = dataJsonStr.decode('GB2312')
dataDict = json.loads(dataJsonStrUni, encoding='GB2312')

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏分布式系统和大数据处理

编写高质量代码:改善C#程序的157个建议

这本书汇集了C#编写中的一些建议、注意事项和小技巧,为了温故知新,又拿出来翻看了一遍。很多主题要阐述的内容是显而易见、不言自明的,就没有再写摘要。部分主题的名称...

573
来自专栏一个会写诗的程序员的博客

从 Java 开始进入 Kotlin的世界: From Java to Kotlin: JKotlinor从 Java 开始进入 Kotlin的世界: From Java to Kotlin: JKo

在前面的内容里,我们已经看到了Java与Kotlin的互操作的基本方式。为了更好的认识Java与Kotlin这两门语言,我们在这里给出一些基本功能,同时使用Ja...

852
来自专栏Java学习网

开发中最常见的Java字符串问题总结

开发中最常见的Java字符串问题总结  1.怎样比较字符串?用”==”还是用equals()?   简单地说,”==”测试两个字符串的引用是否相同,equals...

21310
来自专栏逸鹏说道

Python3 与 C# 扩展之~基础衍生

在线编程: https://mybinder.org/v2/gh/lotapp/BaseCode/master

823
来自专栏Ryan Miao

String的内存模型,为什么String被设计成不可变的

String是Java中最常用的类,是不可变的(Immutable), 那么String是如何实现Immutable呢,String为什么要设计成不可变呢? 前...

28913
来自专栏大内老A

采用一个自创的"验证框架"实现对数据实体的验证[扩展篇]

关于“验证框架”,先后推出了《编程篇》、《设计篇》和《改进篇》,本不打算再写《XXX篇》的。但是今天收到两个园友的短消息,想了解一下如何定义自己的验证规则。这实...

2127
来自专栏流柯技术学院

TestNG 三 测试方法

测试方法是可以带有参数的。每个测试方法都可以带有任意数量的参数,并且可以通过使用TestNG的@Parameters向方法传递正确的参数。

733
来自专栏从零开始学 Web 前端

04 - JavaSE之异常处理

2.throw new someExpresion("错误原因"); 表示的是手动抛出异常。 **

1004
来自专栏青玉伏案

ReactiveSwift源码解析(八) SignalProducer的代码的基本实现

在前面几篇博客中我们详细的聊了ReactiveSwift中的Bag、Event、Observer以及Signal的使用方式和代码实现。那么在接下来的这几篇博客中...

1847
来自专栏分布式系统和大数据处理

ES6中的Promise和Fetch

JavaScript是单线程执行的,因此,为了避免操作时的页面中断(体现为页面假死),可以使用回调函数。但是如果回调函数中仍然嵌套有回调函数,代码就会变得越来越...

1013

扫码关注云+社区