JSON數(shù)據(jù)格式轉(zhuǎn)換為Python的類對(duì)象方法有哪些-創(chuàng)新互聯(lián)

本篇內(nèi)容主要講解“JSON數(shù)據(jù)格式轉(zhuǎn)換為Python的類對(duì)象方法有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“JSON數(shù)據(jù)格式轉(zhuǎn)換為Python的類對(duì)象方法有哪些”吧!

創(chuàng)新互聯(lián)建站專業(yè)IDC數(shù)據(jù)服務(wù)器托管提供商,專業(yè)提供成都服務(wù)器托管,服務(wù)器租用,西云機(jī)房,西云機(jī)房,成都多線服務(wù)器托管等服務(wù)器托管服務(wù)。

  有時(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)語(yǔ)言這一點(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):

  """鄭州人流手術(shù)費(fèi)用 http://www.zzzzyy120.com/

  :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的意思。

到此,相信大家對(duì)“JSON數(shù)據(jù)格式轉(zhuǎn)換為Python的類對(duì)象方法有哪些”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

分享名稱:JSON數(shù)據(jù)格式轉(zhuǎn)換為Python的類對(duì)象方法有哪些-創(chuàng)新互聯(lián)
鏈接URL:http://bm7419.com/article0/gegoo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站維護(hù)、網(wǎng)頁(yè)設(shè)計(jì)公司、App設(shè)計(jì)、定制開發(fā)、網(wǎng)站制作、網(wǎng)站設(shè)計(jì)公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營(yíng)