Code Test - python & JSON

JSON数据在如下地址:https://raw.githubusercontent.com/pengwynn/authentic_jobs/master/test/fixtures/locations.json


看到这个JSON数据的结构,就直接想read整个网页,都不用使用re正则表达式。

题目的要求是获得东南,西南,东北,西北四个方向最远的城市,输出城市名。


我们先获得所有的城市名。

import urllib
import json

# urllib to open the website
response = urllib.urlopen("https://raw.githubusercontent.com/pengwynn/authentic_jobs/master/test/fixtures/locations.json")
source = response.read()

s = json.loads(source)
l = s["locations"]["location"]
for i in l:
    try:
        print i["city"]
    except:
        pass
因为数据中有些并没有city,所以就抓一下异常处理掉。

Austin, Texas
Belfast, Northern Ireland, UK
Boston area
Boston, MA
Boulder, Colorado
Brooklyn , New York
Campbell, CA
Charlotte, VT
Chattanooga, TN
Chicago, IL
College Station, TX
Anywhere
Evanston, IL
Richmond, VA area
Ithaca, NY
Jackson, MI
Jacksonville, FL
Jersey, Channel Islands
Los Angeles.CA
Knoxville, TN
La Quinta, CA
Lewes, Delaware
Lincoln, NE
London, UK
Los Angeles
Maidenhead, UK
Menlo Park, CA
Minneapolis, MN
Mountain View, CA
Nashville, TN
New York, NY
New Zealand
Northern Virginia
Oakland, CA
Olathe, KS
Orlando, Florida
Palo Alto, CA
Philadelphia, PA
Pittsburgh, PA
Portland, OR
Provo, UT
Redwood City, CA
Salt Lake City, UT
San Francisco, CA
Santa Monica, CA
Scotts Valley, CA
Studio City, Ca
Sunnyvale, CA
Toronto
Troy, NY
Tyler, TX
Washington, DC

然后同样的,我们能够获得latitude 和 longitude。然后就是纯粹的对于数字进行比较。

import urllib
import json

# urllib to open the website
response = urllib.urlopen("https://raw.githubusercontent.com/pengwynn/authentic_jobs/master/test/fixtures/locations.json")
source = response.read()

s = json.loads(source)
l = s["locations"]["location"]
lat = []
for i in l:
    try:
        lat.append(i["lat"])
    except:
        pass
lng = []
for i in l:
    try:
        lng.append(i["lng"])
    except:
        pass
lat.sort()
lng.sort()

for i in l:
    try:
        if i["lat"] == lat[0]:
            print "The West City:" + i["city"]
    except:
        pass

就简单的取一个lat最小的城市,输出结果是New Zealand。



####################################################################################################################################

首先,我们可以在IDE中输入help(json)获得json文档。


json模块提供了类似pickle的API,把Python对象转换为JavaScript Object Notation - JSON。 与pickle不同的是,JSON被多种语言运用,尤其在JavaScript,使得JSON在网络项目中非常的适用。JSON几乎是web server端和client端交互使用最广的,对于一个使用Ajax的项目来说。


1. Encoding and Decoding Simple Data Types 转换简单的数据类型

json可以转换几乎所有的python原本的类型,比如string,unicode,int,float,list,tuple,dict... 但是转换为JSON之后再转换回来,可能不会是原本的数据类型。

import json

data = [ { 'a':'A', 'b':(2, 4), 'c':3.0 } ]
data_string = json.dumps(data)
print 'ENCODED:', data_string

decoded = json.loads(data_string)
print 'DECODED:', decoded

print 'ORIGINAL:', type(data[0]['b'])
print 'DECODED :', type(decoded[0]['b'])

# result

ENCODED: [{"a": "A", "c": 3.0, "b": [2, 4]}]
DECODED: [{u'a': u'A', u'c': 3.0, u'b': [2, 4]}]
ORIGINAL: <type 'tuple'>
DECODED : <type 'list'>

我们可以看到,JSON输出的和python repr方法类似。

P.S. 基本来说,string被转换为unicode,tuple被转换为list。



2. 易读性 JSON对比pickle来说更加的具有易读性。

2.1 json.dumps中的sort_key属性

import json

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

unsorted = json.dumps(data)
print 'JSON:', json.dumps(data)
print 'SORT:', json.dumps(data, sort_keys=True)

first = json.dumps(data, sort_keys=True)
second = json.dumps(data, sort_keys=True)

print 'UNSORTED MATCH:', unsorted == first
print 'SORTED MATCH  :', first == second

# result

DATA: [{'a': 'A', 'c': 3.0, 'b': (2, 4)}]
JSON: [{"a": "A", "c": 3.0, "b": [2, 4]}]
SORT: [{"a": "A", "b": [2, 4], "c": 3.0}]
UNSORTED MATCH: False
SORTED MATCH  : True

sort_key用于把JSON字典中的key按照顺序排列,而非继续random排列。


2. json.dumps中的indent属性

import json

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

print 'NORMAL:', json.dumps(data, sort_keys=True)
print 'INDENT:', json.dumps(data, sort_keys=True, indent=2)

# result

DATA: [{'a': 'A', 'c': 3.0, 'b': (2, 4)}]
NORMAL: [{"a": "A", "b": [2, 4], "c": 3.0}]
INDENT: [
  {
    "a": "A", 
    "b": [
      2, 
      4
    ], 
    "c": 3.0
  }
]

indent意味着有缩进的输出。因为JSON的数据一般是具有非常高的嵌套模式。使用了indent,会显示的非常JSON。indent后面跟的非负数,就是说明行缩进是多少。

对于JSON数据,长串的数据确实可以看起来很方便,很对称,但是会消耗更多的bytes,在真实的产品中并不会这样。所以,对于不同的属性进行操作会得到不同的结果,压缩输出的数据模式。

import json


data = [ { 'a':'A', 'b':(2, 4), 'c':3.0 } ]
print 'DATA:', repr(data)
print repr(data)
print 'repr(data)             :', len(repr(data))
print json.dumps(data)
print 'dumps(data)            :', len(json.dumps(data))
print json.dumps(data, indent=2)
print 'dumps(data, indent=2)  :', len(json.dumps(data, indent=2))
print json.dumps(data, separators=(',',':'))
print 'dumps(data, separators):', len(json.dumps(data, separators=(',',':')))


# result


DATA: [{'a': 'A', 'c': 3.0, 'b': (2, 4)}]
[{'a': 'A', 'c': 3.0, 'b': (2, 4)}]
repr(data)             : 35
[{"a": "A", "c": 3.0, "b": [2, 4]}]
dumps(data)            : 35
[
  {
    "a": "A", 
    "c": 3.0, 
    "b": [
      2, 
      4
    ]
  }
]
dumps(data, indent=2)  : 76
[{"a":"A","c":3.0,"b":[2,4]}]
dumps(data, separators): 29

如上,我们可以看到不同的属性进行设置之后,得到的数据长度的不同。json.dumps的separators属性,是一个tuple,default就是包含逗号,冒号,然后处理的时候去除空格,压缩整个输出数据。



3. Encoding Dictionaries 解析字典

JSON格式希望keys在字典中都是string类型的。如果有其他类型的key,那么解析过程就会报错。可以抓取异常,或者使用关键词skipkeys来跳过不是string的keys。

import json

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

print 'First attempt'
try:
    print json.dumps(data)
except (TypeError, ValueError) as err:
    print 'ERROR:', err

print
print 'Second attempt'
print json.dumps(data, skipkeys=True)

# result

First attempt
ERROR: keys must be a string

Second attempt
[{"a": "A", "c": 3.0, "b": [2, 4]}]

我们能看到,如果有string,那么会有异常,keys must be a string。如果跳过的话就输出所有是string的key。



转载关于JSON自定义和JSON自带的Encode和Decode方法

处理自己的数据类型

JSON模块不仅可以处理普通的python内置类型,也可以处理自定义的数据类型,而往往处理自定义的对象是很常用的。

首先,自定义一个Person类。

class Person(object):
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __repr__(self):
        return 'Person Object name : %s , age : %d' % (self.name,self.age)
if __name__  == '__main__':
    p = Person('Peter',22)
    print p

如果直接通过json.dumps方法对Person的实例进行处理的话,会报错,因为json无法支持这样的自动转化。通过上面所提到的json和python的类型转化对照表,可以发现,object类型是和dict相关联的,所以我们需要把我们自定义的类型转化为dict,然后再进行处理。这里,有两种方法可以使用。

方法一:自己写转换函数

class Person(object):
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __repr__(self):
        return 'Person Object name : %s , age : %d' % (self.name,self.age)
if __name__  == '__main__':
    p = Person('Peter',22)
    print p

import json
 
p = Person('Peter',22)
 
def object2dict(obj):
    #convert object to a dict
    d = {}
    d['__class__'] = obj.__class__.__name__
    d['__module__'] = obj.__module__
    d.update(obj.__dict__)
    return d
 
def dict2object(d):
    #convert dict to object
    if'__class__' in d:
        class_name = d.pop('__class__')
        module_name = d.pop('__module__')
        module = __import__(module_name)
        class_ = getattr(module,class_name)
        args = dict((key.encode('ascii'), value) for key, value in d.items()) #get args
        inst = class_(**args) #create new instance
    else:
        inst = d
    return inst
 
d = object2dict(p)
print d
#{'age': 22, '__module__': 'Person', '__class__': 'Person', 'name': 'Peter'}
 
o = dict2object(d)
print type(o),o
#<class 'Person.Person'> Person Object name : Peter , age : 22
 
dump = json.dumps(p,default=object2dict)
print dump
#{"age": 22, "__module__": "Person", "__class__": "Person", "name": "Peter"}
 
load = json.loads(dump,object_hook = dict2object)
print load
#Person Object name : Peter , age : 22


上面代码已经写的很清楚了,实质就是自定义object类型和dict类型进行转化。object2dict函数将对象模块名、类名以及__dict__存储在dict对象里,并返回。dict2object函数则是反解出模块名、类名、参数,创建新的对象并返回。在json.dumps 方法中增加default参数,该参数表示在转化过程中调用指定的函数,同样在decode过程中json.loads方法增加object_hook,指定转化函数。


方法二: 继承JSONEncoder和JSONDecoder类,override相关方法

JSONEncoder类负责编码,主要是通过其default函数进行转化,我们可以override该方法。同理对于JSONDecoder。

class Person(object):
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __repr__(self):
        return 'Person Object name : %s , age : %d' % (self.name,self.age)
if __name__  == '__main__':
    p = Person('Peter',22)
    print p

import json
 
p = Person('Peter',22)
 
class MyEncoder(json.JSONEncoder):
    def default(self,obj):
        #convert object to a dict
        d = {}
        d['__class__'] = obj.__class__.__name__
        d['__module__'] = obj.__module__
        d.update(obj.__dict__)
        return d
 
class MyDecoder(json.JSONDecoder):
    def __init__(self):
        json.JSONDecoder.__init__(self,object_hook=self.dict2object)
    def dict2object(self,d):
        #convert dict to object
        if'__class__' in d:
            class_name = d.pop('__class__')
            module_name = d.pop('__module__')
            module = __import__(module_name)
            class_ = getattr(module,class_name)
            args = dict((key.encode('ascii'), value) for key, value in d.items()) #get args
            inst = class_(**args) #create new instance
        else:
            inst = d
        return inst
 
 
d = MyEncoder().encode(p)
o =  MyDecoder().decode(d)
 
print d
print type(o), o

# result

Person Object name : Peter , age : 22
{"age": 22, "__module__": "__main__", "__class__": "Person", "name": "Peter"}
<class '__main__.Person'> Person Object name : Peter , age : 22


参考:

http://pymotw.com/2/json/

http://www.pythonforbeginners.com/json/

http://www.cnblogs.com/coser/archive/2011/12/14/2287739.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值