文章出處

Python中的json操作

標簽(空格分隔): python 編碼 json


字符串前綴問題

字符串前綴可以有r,u
r:表示原始(raw)字符串,比如'\n'不會被轉義。常用于正則。

u:表示unicode字符串。
python3系列的字符串默認是unicode,無需用u進行轉碼。我用的是python2.7,所以還是要手動處理編碼。

發生問題的一個場景是:從某個url抓取json格式數據,import了python自帶的jsonsimplejson包,調用其loads()方法后,得到的對象(字典)的key的類型是unicode,形如:

obj={
    u'name':'chris',
    u'age':22
}

而我當前的一個函數,傳入參數為一個dict字典,用它生成為sql語句,帶著u的insert語句插入數據庫會報錯。需要去除u

u是unicode類型,不帶u的是字符串類型。對于一個unicode變量,可以用encode()函數轉為str類型。但是現在有一整個字典的key都要轉換,我不知道怎么轉換。

一個解決方法是重寫一個json構建/解析的函數。我并不想重復造輪子,只是python2.7下json和simplejson兩個包太難用。嘗試了各種參數,還是無法得到key為str類型而不是unicode類型的結果。

我傳給你的是ascii編碼的對象,為什么不能返還給我一個ascii編碼的對象?果斷自己寫一個好用的。

一個簡陋的json構建/解析實現

          dumps(序列化)
     -------------------> 
 obj                        str
 對象                       字符串
     <-------------------
         loads(反序列化)
    

這里采用類似dumps和loads的名字,不過加了自己的前綴。
從obj對象(python中是字典類型)到str類型,是序列化(dumps)的過程;把str解析后裝載為obj對象,是反序列化(loads)的過程。序列化目的在于網絡傳輸。

#!/usr/bin/python
#coding:utf-8

import types

#從obj到str
def chris_dumps(dict_data):
    jar=""
    result = chris_dumps_iter(dict_data, jar)
    return "{"+result+"}"

def chris_dumps_iter(dict_data, jar):
    for k in dict_data:
        jar = jar + "\"" + k + "\": "
        if isinstance(dict_data[k], dict):
            tmp = chris_dumps(dict_data[k])
            jar = jar+tmp
        elif isinstance(dict_data[k], basestring):
            jar = jar + "\""+dict_data[k]+"\""
        else:
            jar = jar + str(dict_data[k])
        jar = jar + ", "
    return jar[0:len(jar)-2]

#從str到objs
def chris_loads(data):
    jar = {}
    result = chris_loads_iter(data, jar)
    return result

def chris_loads_iter(data, jar):
    cnt = 0  # count brackets  {:+1   }:-1
    key = ""
    val = ""
    quote=False
    colon = False   # 冒號,False表示在冒號左邊,True表示在右邊
    #for i in xrange(len(data)):
    i=0
    while i<len(data):
        if quote:            
            if data[i]=="\"": #右引號
                if colon==False: 
                    quote=False
                else:
                    val += data[i]
            else:
                key += data[i]
                
        else:
            if data[i]=="\"": #左引號
                if colon==False:
                    quote=True
                    key = ""
                else:
                    val += data[i]
            elif data[i]==":":
                colon = True
            elif data[i]=="," or data[i]=='}':
                #jar[key]=eval(val) #干的漂亮!
                jar[key]=eval(val)
                val = ""
                colon = False
            elif data[i]==" ":
                pass
            elif data[i]=="{":
                if colon==True :
                    j=i
                    subdata = ""
                    while data[j]!='}':
                        subdata += data[j]
                        j += 1
                    subdata += "}"
                    i=j+1
                    sub_result = chris_loads(subdata)
                    val=sub_result
                    jar[key]=sub_result
                    val = ""
                    colon = False
            else:
                val += data[i]
        i += 1 
    return jar

寫好了,測試一下:

if __name__ == "__main__":
    s1={'name':'chris', 'age': 22}
    s={'name':'chris', 'age':22, 'property': { 'id': 2011, 'lang': 'chinese'}}
    t=chris_dumps(s)
    g=s['property']
     
    print 't:', t
    q=chris_loads(t)
    print 'q:', q
    print type(q)

P.S.其實這個loads函數寫的并不優美,正確的思路應當是畫出狀態自動機,列出每種情況以及各個情況之間的轉化關系。


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()