I am using Jackson parser for parsing for Java object to JSON . I am forcefully adding JSON keys for some java objects, using the following code.
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes({ @JsonSubTypes.Type(value = A.class, name = "a"),
@JsonSubTypes.Type(value = F.class, name = "f") })
I am having same set classes in Python also. I would like to do the same thing in python. But not sure about what are the alternatives for this Jackson annotation available in python.
My requirement is that I have to send a POST request to a REST API. I need to serialize the java object into JSON. But as my class structure is a little bit different I don't have all the JSON keys mentioned handy in java classes. To solve the issue what I am doing is that I am adding 'a' key in JSON when it finds 'A' object is passed from java. It is doing the same thing for 'F' object. So, I have achieved the solution the way I mentioned above. I want to achieve the same thing in Python.
Is there some JSON parser available what does the same thing as mentioned above, or I have to follow some different approach for that?
I would strongly recommend the pydantic library, which also provides the possibility to add validations of the data.
It is very easy and straightforward to use, also if you only use it for json marshalling/unmarshalling.
https://pypi.org/project/pydantic/
import json
from datetime import datetime
from pydantic import BaseModel
class MyInnerClass(BaseModel):
timestamp: datetime
some_string: str
class MyOuterClass(BaseModel):
inner_instance: MyInnerClass
other_string: str
# Class to json
test_class = MyOuterClass(inner_instance=MyInnerClass(timestamp=datetime(2022, 6, 22), some_string="some"),
other_string="other")
json_string = test_class.json()
# Json to Class
input_string = '{"inner_instance": {"timestamp": "2022-06-22T00:00:00", "some_string": "some"}, "other_string": "other"}'
loaded_class = MyOuterClass(**json.loads(input_string))
attrs + cattrs is very close for the task.
copy one cattr example here,
>>> import attr, cattr
>>>
>>> @attr.s(slots=True, frozen=True) # It works with normal classes too.
... class C:
... a = attr.ib()
... b = attr.ib()
...
>>> instance = C(1, 'a')
>>> cattr.unstructure(instance)
{'a': 1, 'b': 'a'}
>>> cattr.structure({'a': 1, 'b': 'a'}, C)
C(a=1, b='a')
but it's not as capable as Jackson, i've not yet been able to find a solution to map attribute between serialized json and deserialized python object.
I have the same problem and could not find anything suitable. So I wrote pyson
https://tracinsy.ewi.tudelft.nl/pubtrac/Utilities/wiki/pyson
It's still under development and I will add new features along the way. It's not ment to be a complete substitute for jackson as jackson is huge. I just implement what I need, in jackson style where possible.
I think the most similar option you will get in python ecosystem will be jsonpickle
although it's not as complete as complete Jackson. python engineers and users chose a different respectable perspective and that is using schema-less approaches to problems so typing oriented serialization libraries like Jackson doesn't have a strong equivalent in Python.
You can use Jsonic library.
Jsonic is a lightweight utility for serializing/deserializing python objects to/from JSON.
Jsonic allows serializing/deserializing to/from specific Class instances.
It supports many of the functionalities Jackson supports in Java.
Example:
from jsonic import serialize, deserialize
class User(Serializable):
def __init__(self, user_id: str, birth_time: datetime):
super().__init__()
self.user_id = user_id
self.birth_time = birth_time
user = User('id1', datetime(2020,10,11))
obj = serialize(user) # {'user_id': 'id1', 'birth_time': {'datetime': '2020-10-11 00:00:00', '_serialized_type': 'datetime'}, '_serialized_type': 'User'}
# Here the magic happens
new_user : User = deserialize(obj) # new_user is a new instance of user with same attributes
Jsonic has some nifty features:
Here you can find some more advanced example:
from jsonic import Serializable, register_jsonic_type, serialize, deserialize
class UserCredentials:
"""
Represents class from some other module, which does not extend Serializable
We can register it using register_serializable_type function
"""
def __init__(self, token: str, exp: datetime):
self.token = token
self.expiration_time = exp
self.calculatedAttr = random.uniform(0, 1)
# Register UserCredentials which represents class from another module that does not implement Serializable
# exp __init__ parameter is mapped to expiration_time instace attribute
register_jsonic_type(UserCredentials, init_parameters_mapping={'exp': 'expiration_time'})
class User(Serializable):
transient_attributes = ['user_calculated_attr'] # user_calculated_attr won't be serialized and deserialzied
init_parameters_mapping = {'id': 'user_id'} # id __init__ parameter is mapped to user_id instace attribute
def __init__(self, user_id: str, birth_time: datetime, user_credentials: UserCredentials, *args):
super().__init__()
self.user_id = user_id
self.birth_time = birth_time
self.user_credentials = user_credentials
self.user_calculated_attr = 'user_calculated_attr'
user = User(user_id='user_1', birth_time=datetime(1995, 7, 5, 0),
user_credentials=UserCredentials(token='token', exp=datetime(2020, 11, 1, 0)))
# Here the magic happens
user_json_obj = serialize(user, string_output=True)
new_user = deserialize(user_json_obj, string_input=True, expected_type=User)
Full disclosure: I'm the creator of Jsonic, i recommend you read the Jsonic GitHub repository README to see if it fits your needs.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.