最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

把JSON數(shù)據(jù)格式轉(zhuǎn)換為Python的類對(duì)象方法詳解(兩種方法)

 更新時(shí)間:2019年06月04日 16:21:38   作者:昀溪  
本文通過兩種方法給大家介紹了把JSON數(shù)據(jù)格式轉(zhuǎn)換為Python的類對(duì)象,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下

JOSN字符串轉(zhuǎn)換為自定義類實(shí)例對(duì)象

有時(shí)候我們有這種需求就是把一個(gè)JSON字符串轉(zhuǎn)換為一個(gè)具體的Python類的實(shí)例,比如你接收到這樣一個(gè)JSON字符串如下:

{"Name": "Tom", "Sex": "Male", "BloodType": "A", "Hobbies": ["籃球", "足球"]}

我需要把這個(gè)轉(zhuǎn)換為具體的一個(gè)Person類的實(shí)例,通過對(duì)象的方式來進(jìn)行操作。在Java中有很多實(shí)現(xiàn)比如Gson或者FastJosn。如下代碼所示(這里不是全部代碼,值標(biāo)識(shí)最主要的部分):

import com.alibaba.fastjson.JSONObject;
import com.example.demo.entity.Product;
String a = "{\"gmtCreate\":1559009853000,\"dataFormat\":1,\"deviceCount\":1,\"nodeType\":0,\"productKey\":\"a1U85pSQrAz\",\"productName\":\"溫度計(jì)\"}";
//JSON字符串反序列化為一個(gè)Product對(duì)象
Product product = JSONObject.parseObject(a, Product.class);

上述這種需求一般發(fā)生在前段傳遞過來JSON字符串或者其他系統(tǒng)進(jìn)行RPC通信的時(shí)候也發(fā)送過來JSON字符串,作為接收端需要反序列化成對(duì)象來進(jìn)行處理,而且Fastjson里還有一個(gè)JSONArray.parseArray方法可以轉(zhuǎn)換為對(duì)象列表。可是在Python沒有像Java中這么方便的東西。

從網(wǎng)上論壇中也看到過一些,不過很多都是效果有但是使用起來麻煩,所以我這里也來說一下我的思路。

方式1:通過josn.loads來實(shí)現(xiàn)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import json
class Person:
 def __init__(self, data=None):
  self._name = "1"
  self._sex = ""
  self._blood_type = "O"
  self._hobbies = []
  self._date_of_birth = "1900/1/1"
  if data:
   self.__dict__ = data
 # 通過屬性的方式來獲取和設(shè)置實(shí)例變量的值,如果不這樣那么就只能通過set或者get方法來做
 @property
 def date_of_brith(self):
  return self._date_of_birth
 @date_of_brith.setter
 def date_of_brith(self, date_of_brith):
  self._date_of_birth = date_of_brith
def main():
 try:
  str1 = '{"name": "Tom", "sex": "male", "blood_type": "A", "hobbies": ["籃球", "足球"]}'
  person1 = json.loads(str1, object_hook=Person)
  print(isinstance(person1, Person))
  # 這里你會(huì)發(fā)現(xiàn)沒有date_of_brith這個(gè)內(nèi)容
  print(person1.__dict__)
  # 獲取date_of_brith屬性值報(bào)錯(cuò),因?yàn)镴SON字符串不包含這個(gè)鍵,但是類中的實(shí)例變量有這個(gè),正常來講你應(yīng)該可以獲取默認(rèn)值,但是由于
  # 替換了__dict__,所以就沒有了,因?yàn)開_dict__原本就是實(shí)例變量的字典形式,你替換了自然也就找不到原來的了。
  # print(person.date_of_brith)
  # 下面我們通過正常的方式實(shí)例化一個(gè)對(duì)象
  person2 = Person()
  print(person2.__dict__)
  print(person2.date_of_brith)
 except Exception as err:
  print(err)
if __name__ == "__main__":
 try:
  main()
 finally:
  sys.exit()

object_hook的含義是,默認(rèn)json.loads()返回的是dict,你可以使用object_hook來讓其返回其他類型的值,它這里實(shí)現(xiàn)的原理就是把你傳遞進(jìn)來的JSON字符串傳遞給了object_hook指定的方法或者類(如果是類的話則會(huì)執(zhí)行__init__方法,其實(shí)就是實(shí)例化),這時(shí)候在類的__init方法中我們通過賦值給self.dict__,其實(shí)這就等于對(duì)Person類的實(shí)例變量做了替換,除非你的JSON字符串的鍵和實(shí)例變量的名稱以及數(shù)量一致否則你無法通過你在類里定義的實(shí)例變量名稱獲取通過JSON字符串傳遞進(jìn)去的值。如下圖:

所以通過上面可以看出來,這個(gè)過程不是為實(shí)例變量賦值的過程而是一個(gè)替換的過程,Python是動(dòng)態(tài)語言這一點(diǎn)和JAVA不同。如果你在程序中用單下劃線標(biāo)識(shí)變量為私有(只是規(guī)范而不是真正的私有)那么你傳遞的JSON字符串的鍵也需要有下劃線,這樣你通過實(shí)例的方法才能獲取。既然額外增加下劃線不太現(xiàn)實(shí),那么有沒有其他辦法呢?看方式2

方式2:通過反射機(jī)制來實(shí)現(xiàn)

先看一下類的定義

#!/usr/bin/env python
# -*- coding: utf-8 -*-
class Person:
 def __init__(self):
  self._name = "1"
  self._sex = ""
  self._blood_type = "O"
  self._hobbies = []
  self._date_of_birth = "1900/1/1"
 def __str__(self):
  """
  輸出實(shí)例的類名字,而不是一個(gè)地址
  :return: 該實(shí)例的類名字
  """
  return self.__class__.__name__
 # 當(dāng)一個(gè)方法加上這個(gè)裝飾器之后,hasattr()中的屬性要寫成這個(gè)方法的名稱,而不是實(shí)例變量的名稱。
 # 如果不加這個(gè)裝飾器,那么hasattr()中的屬性名稱要和實(shí)例變量的名稱保持一致
 @property
 def Name(self):
  return self._name
 @Name.setter
 def Name(self, name):
  self._name = name
 @property
 def Sex(self):
  return self._sex
 @Sex.setter
 def Sex(self, sex):
  self._sex = sex
 @property
 def BloodType(self):
  return self._blood_type
 @BloodType.setter
 def BloodType(self, blood_type):
  self._blood_type = blood_type
 @property
 def Hobbies(self):
  return self._hobbies
 @Hobbies.setter
 def Hobbies(self, hobbies):
  self._hobbies = hobbies
 @property
 def date_of_brith(self):
  return self._date_of_birth
 @date_of_brith.setter
 def date_of_brith(self, date_of_brith):
  self._date_of_birth = date_of_brith

下面看看轉(zhuǎn)換的方法

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import json
import importlib
def get_instance(str_stream, class_full_path=None):
 """
 :param str_stream: json的字符串形式 '{"Name": "Tom", "Sex": "Male", "BloodType": "A"}'
 :param class_full_path: package.module.class
 :return:
 """
 try:
  json_obj = json.loads(str_stream)
 except Exception as err:
  print("輸入的字符串不符合JSON格式,請(qǐng)檢查。")
  return None
 if class_full_path is None:
  return json_obj
 else:
  try:
   # 獲取模塊路徑
   module_path = ".".join(class_full_path.split(".")[0:-1])
   # 獲取類名稱
   class_name = class_full_path.split(".")[-1]
   # 通過模塊名加載模塊
   CC = importlib.import_module(module_path)
   # 判斷是否有class_name所代表的屬性
   if hasattr(CC, class_name):
    # 獲取模塊中屬性
    temp_obj = getattr(CC, class_name)
    # 實(shí)例化對(duì)象
    obj = temp_obj()
    for key in json_obj.keys():
     obj.__setattr__(key, json_obj[key])
    return obj
   else:
    pass
  except Exception as err:
   print(err)
   return None
def main():
 try:
  str1 = '{"Name": "Tom", "Sex": "Male", "BloodType": "A", "Hobbies": ["籃球", "足球"]}'
  person1 = get_instance(str1, class_full_path="AAA.Classes.Person")
  # 查看類型
  print(type(person1))
  # 查看屬性
  print(person1.__dict__)
  # 查看指定屬性
  print(person1.Name)
 except Exception as err:
  print(err)
if __name__ == "__main__":
 try:
  main()
 finally:
  sys.exit()

__import__() 有2個(gè)參數(shù),第一個(gè)是類,第二個(gè)是fromlist,如果不寫fromlist,則按照下面的寫法會(huì)只導(dǎo)入AAA包,如果fromlist有值則會(huì)導(dǎo)入AAA下面的Classes模塊cc = __import__("AAA.Classes", fromlist=True)不寫fromlist 相當(dāng)于 import AAA ,如果寫了就相當(dāng)于是from AAA import Classes編程時(shí)如果使用動(dòng)態(tài)加載建議使用importlib.import_module(),而不是__import__()。

下面看一下效果:

可以看到,這樣操作之后就是給實(shí)例變量賦值而不是像之前那樣的替換,而且保留了類中實(shí)例變量的私有規(guī)范。不過需要說明的是JSON字符串中的鍵名稱要和類里面定義的屬性名稱一樣,也就是鍵名稱要和類中@property裝飾的方法同名。我們也可以看到這種使用方式也有默認(rèn)JSONObject.parseObject的意思。

不過這只是一個(gè)簡單的實(shí)現(xiàn),只能通過單一JSON字符串生成對(duì)象不能生成對(duì)象列表。當(dāng)然有興趣的朋友可以自己根據(jù)這個(gè)思路進(jìn)行擴(kuò)展。

另外既然無論是loads還是我自己的方法搜需要保證JSON字符串的鍵和變量名稱一致大家就不要糾結(jié)于名稱一致的問題,但是我的方法做到了保持實(shí)例變量命名、操作實(shí)例屬性時(shí)候的規(guī)范,同時(shí)對(duì)類也沒有過多的入侵性而不像loads方法中還需要在類的init方法里面增加不必要的內(nèi)容。在我這個(gè)方法中如果能實(shí)現(xiàn)忽略大小寫通用性就更好了。歡迎大家來提供思路。

總結(jié)

以上所述是小編給大家介紹的把JSON數(shù)據(jù)格式轉(zhuǎn)換為Python的類對(duì)象方法詳解,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • python的變量與賦值詳細(xì)分析

    python的變量與賦值詳細(xì)分析

    這篇文章主要介紹了python的變量與賦值詳細(xì)分析,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • 深入解析Python中的線程同步方法

    深入解析Python中的線程同步方法

    Python盡管可以創(chuàng)建多條線程,但是由于GIL的存在,Python的多條線程并不能同時(shí)運(yùn)行,因而線程間的同步便顯得更為重要,這里我們就來深入解析Python中的線程同步方法,需要的朋友可以參考下
    2016-06-06
  • 使用python實(shí)現(xiàn)rsa算法代碼

    使用python實(shí)現(xiàn)rsa算法代碼

    RSA算法是一種非對(duì)稱加密算法,是現(xiàn)在廣泛使用的公鑰加密算法,主要應(yīng)用是加密信息和數(shù)字簽名。本文給大家介紹python實(shí)現(xiàn)rsa算法代碼,感興趣的朋友一起學(xué)習(xí)吧
    2016-02-02
  • 一文帶你玩轉(zhuǎn)Python屬性和方法

    一文帶你玩轉(zhuǎn)Python屬性和方法

    Python是一種簡潔而強(qiáng)大的編程語言,其支持面向?qū)ο蟮木幊谭妒剑疚膶娜腴T到精通介紹Python中的屬性和方法,幫助大家深入了解這些重要的概念,并學(xué)會(huì)如何在實(shí)際開發(fā)中靈活應(yīng)用它們
    2023-07-07
  • 基于Python_腳本CGI、特點(diǎn)、應(yīng)用、開發(fā)環(huán)境(詳解)

    基于Python_腳本CGI、特點(diǎn)、應(yīng)用、開發(fā)環(huán)境(詳解)

    下面小編就為大家?guī)硪黄赑ython_腳本CGI、特點(diǎn)、應(yīng)用、開發(fā)環(huán)境(詳解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-05-05
  • tornado捕獲和處理404錯(cuò)誤的方法

    tornado捕獲和處理404錯(cuò)誤的方法

    這篇文章主要介紹了tornado捕獲和處理404錯(cuò)誤的方法,方法很簡單,只要覆寫write_error方法就可以,看下面的代碼就明白了
    2014-02-02
  • Python+OpenCV人臉識(shí)別簽到考勤系統(tǒng)實(shí)現(xiàn)(附demo)

    Python+OpenCV人臉識(shí)別簽到考勤系統(tǒng)實(shí)現(xiàn)(附demo)

    本文主要介紹了Python+OpenCV人臉識(shí)別簽到考勤系統(tǒng)實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • 詳解Python調(diào)試神器之PySnooper

    詳解Python調(diào)試神器之PySnooper

    在程序開發(fā)過程中,代碼的運(yùn)行往往會(huì)和我們預(yù)期的結(jié)果有所差別。于是,我們需要清楚代碼運(yùn)行過程中到底發(fā)生了什么?代碼哪些模塊運(yùn)行了,哪些模塊沒有運(yùn)行?輸出的局部變量是什么樣的?PySnooper,能夠大大減少調(diào)試過程中的工作量
    2021-11-11
  • 淺談python連續(xù)賦值可能引發(fā)的錯(cuò)誤

    淺談python連續(xù)賦值可能引發(fā)的錯(cuò)誤

    今天小編就為大家分享一篇淺談python連續(xù)賦值可能引發(fā)的錯(cuò)誤,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-11-11
  • gethostbyaddr在Python3中引發(fā)UnicodeDecodeError

    gethostbyaddr在Python3中引發(fā)UnicodeDecodeError

    本文介紹了gethostbyaddr()在Python?3中引發(fā)UnicodeDecodeError的處理方法,對(duì)大家解決問題具有一定的參考價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-05-05

最新評(píng)論

宜昌市| 鄂托克前旗| 墨玉县| 明星| 密云县| 开阳县| 平阴县| 兴国县| 乌恰县| 永城市| 昌邑市| 清涧县| 三门峡市| 鱼台县| 峨边| 宣汉县| 北辰区| 南昌市| 广南县| 阳谷县| 巨鹿县| 双桥区| 涟水县| 鄄城县| 湘阴县| 林口县| 砀山县| 兴山县| 阳谷县| 花垣县| 富锦市| 枞阳县| 全南县| 滨州市| 宜章县| 罗山县| 临湘市| 大冶市| 桐城市| 峡江县| 汶上县|