中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》
  • 首頁 > 
  • 教程 > 
  • 開發技術 > 
  • 把JSON數據格式轉換為Python的類對象方法詳解(兩種方法)

把JSON數據格式轉換為Python的類對象方法詳解(兩種方法)

發布時間:2020-09-19 09:21:21 來源:腳本之家 閱讀:462 作者:昀溪 欄目:開發技術

JOSN字符串轉換為自定義類實例對象

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

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

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

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

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

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

方式1:通過josn.loads來實現

#!/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
 # 通過屬性的方式來獲取和設置實例變量的值,如果不這樣那么就只能通過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))
  # 這里你會發現沒有date_of_brith這個內容
  print(person1.__dict__)
  # 獲取date_of_brith屬性值報錯,因為JSON字符串不包含這個鍵,但是類中的實例變量有這個,正常來講你應該可以獲取默認值,但是由于
  # 替換了__dict__,所以就沒有了,因為__dict__原本就是實例變量的字典形式,你替換了自然也就找不到原來的了。
  # print(person.date_of_brith)
  # 下面我們通過正常的方式實例化一個對象
  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的含義是,默認json.loads()返回的是dict,你可以使用object_hook來讓其返回其他類型的值,它這里實現的原理就是把你傳遞進來的JSON字符串傳遞給了object_hook指定的方法或者類(如果是類的話則會執行__init__方法,其實就是實例化),這時候在類的__init方法中我們通過賦值給self.dict__,其實這就等于對Person類的實例變量做了替換,除非你的JSON字符串的鍵和實例變量的名稱以及數量一致否則你無法通過你在類里定義的實例變量名稱獲取通過JSON字符串傳遞進去的值。如下圖:

把JSON數據格式轉換為Python的類對象方法詳解(兩種方法)

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

方式2:通過反射機制來實現

先看一下類的定義

#!/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):
  """
  輸出實例的類名字,而不是一個地址
  :return: 該實例的類名字
  """
  return self.__class__.__name__
 # 當一個方法加上這個裝飾器之后,hasattr()中的屬性要寫成這個方法的名稱,而不是實例變量的名稱。
 # 如果不加這個裝飾器,那么hasattr()中的屬性名稱要和實例變量的名稱保持一致
 @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

下面看看轉換的方法

#!/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格式,請檢查。")
  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)
    # 實例化對象
    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個參數,第一個是類,第二個是fromlist,如果不寫fromlist,則按照下面的寫法會只導入AAA包,如果fromlist有值則會導入AAA下面的Classes模塊cc = __import__("AAA.Classes", fromlist=True)不寫fromlist 相當于 import AAA ,如果寫了就相當于是from AAA import Classes編程時如果使用動態加載建議使用importlib.import_module(),而不是__import__()。

下面看一下效果:

把JSON數據格式轉換為Python的類對象方法詳解(兩種方法)

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

不過這只是一個簡單的實現,只能通過單一JSON字符串生成對象不能生成對象列表。當然有興趣的朋友可以自己根據這個思路進行擴展。

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

總結

以上所述是小編給大家介紹的把JSON數據格式轉換為Python的類對象方法詳解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對億速云網站的支持!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

温泉县| 绍兴市| 年辖:市辖区| 桐乡市| 漾濞| 张家口市| 喀喇| 谷城县| 洪泽县| 兴宁市| 寻甸| 潞城市| 齐齐哈尔市| 西贡区| 依兰县| 茶陵县| 沙坪坝区| 清镇市| 东兰县| 海晏县| 晋宁县| 营山县| 曲松县| 和田市| 临漳县| 瓮安县| 饶平县| 大邑县| 金昌市| 南宁市| 和田县| 垦利县| 调兵山市| 新河县| 浠水县| 朝阳县| 读书| 开阳县| 威宁| 桂阳县| 朔州市|