Serializing and Deserializing object with JSON - python

Is there a way or a library made to deserialize a JSON string into a typed object in ActionScript and Python?
For eg.
class Person
{
String name;
int age;
}
Person person = new Person("John", "22");
String jsonString = JSON.Serialize(person);
Person person2 = (Person) JSON.Deserialize(jsonString);
So, the last statement basically casts the object we get after deserializing the jsonString into the Person object.

I can only speak for Python. There is a built in library for JSON access, it can be viewed in the docs here.
Unfortunately, out of the box, you cannot serialize/deserialize objects, just dicts, lists and simply types. You have to write specific object encoders to do so. This is pretty much covered in the docs.

For AS3 you can use as3corelib by Mike Chambers.
https://github.com/mikechambers/as3corelib/tree/master/src/com/adobe/serialization/json
Edit: After some Googling I ended up back on SO at this question: Typed AS3 JSON Encoder and Decoder? It seems that there is a library for doing typed deserialization, but it is not totally robust and fails on some data types. If you think you can handle the restrictions then it might be the best option short of writing your own parser or gettting into something heavy like BlazeDS.
http://code.google.com/p/ason/

Please try with this:
import json
class Serializer:
#staticmethod
def encode_obj(obj):
if type(obj).__name__ =='instance':
return obj.__dict__
#staticmethod
def serialize(obj):
return json.dumps(obj, default=Serializer.encode_obj)
class TestClass:
def __init__(self):
self.a = 1
t = TestClass()
json_str = Serializer.serialize(t)

Short answer: No there is not. JSON doesn't include typed objects except for a few such as Arrays. The as3Corelib does recognize these. But as you mentioned, you get back an Object with name value pairs. Since JSON does not contain your custom actionscript classes, there is no automatic way to convert a JSON object into a typed actionscript object.
The as3corelib is a great utility for JSON in flash. However the latest build of the flash player (version 10.3) includes JSON as a native data type.
But it is not very difficult to create a class with a constructor that takes the JSON object as an argument, and you can parse it into the class variables. I have to do this all the time when working with the facebook Graph API.

Related

"ObjectId' object is not iterable" error, while fetching data from MongoDB Atlas

Okay, so pardon me if I don't make much sense. I face this 'ObjectId' object is not iterable whenever I run the collections.find() functions. Going through the answers here, I'm not sure where to start. I'm new to programming, please bear with me.
Every time I hit the route which is supposed to fetch me data from Mongodb, I getValueError: [TypeError("'ObjectId' object is not iterable"), TypeError('vars() argument must have __dict__ attribute')].
Help
Exclude the "_id" from the output.
result = collection.find_one({'OpportunityID': oppid}, {'_id': 0})
I was having a similar problem to this myself. Not having seen your code I am guessing the traceback similarly traces the error to FastAPI/Starlette not being able to process the "_id" field - what you will therefore need to do is change the "_id" field in the results from an ObjectId to a string type and rename the field to "id" (without the underscore) on return to avoid incurring issues with Pydantic.
First of all, if we had some examples of your code, this would be much easier. I can only assume that you are not mapping your MongoDb collection data to your Pydantic BaseModel correctly.
Read this:
MongoDB stores data as BSON. FastAPI encodes and decodes data as JSON strings. BSON has support for additional non-JSON-native data types, including ObjectId which can't be directly encoded as JSON. Because of this, we convert ObjectIds to strings before storing them as the _id.
I want to draw attention to the id field on this model. MongoDB uses _id, but in Python, underscores at the start of attributes have special meaning. If you have an attribute on your model that starts with an underscore, pydantic—the data validation framework used by FastAPI—will assume that it is a private variable, meaning you will not be able to assign it a value! To get around this, we name the field id but give it an alias of _id. You also need to set allow_population_by_field_name to True in the model's Config class.
Here is a working example:
First create the BaseModel:
class PyObjectId(ObjectId):
""" Custom Type for reading MongoDB IDs """
#classmethod
def __get_validators__(cls):
yield cls.validate
#classmethod
def validate(cls, v):
if not ObjectId.is_valid(v):
raise ValueError("Invalid object_id")
return ObjectId(v)
#classmethod
def __modify_schema__(cls, field_schema):
field_schema.update(type="string")
class Student(BaseModel):
id: PyObjectId = Field(default_factory=PyObjectId, alias="_id")
first_name: str
last_name: str
class Config:
allow_population_by_field_name = True
arbitrary_types_allowed = True
json_encoders = {ObjectId: str}
Now just unpack everything:
async def get_student(student_id) -> Student:
data = await collection.find_one({'_id': student_id})
if data is None:
raise HTTPException(status_code=404, detail='Student not found.')
student: Student = Student(**data)
return student
Use the response model inside app decorator Here is the sample example
from pydantic import BaseModel
class Todo(BaseModel):
title:str
details:str
main.py
#app.get("/{title}",response_model=Todo)
async def get_todo(title:str):
response=await fetch_one_todo(title)
if not response:
raise
HTTPException(status_code=status.HTTP_404_NOT_FOUND,detail='not found')
return response
use db.collection.find(ObjectId:"12348901384918")
here db.collection is database name and use double quotes for the string .
I was trying to iterate through all the documents and what worked for me was this solution https://github.com/tiangolo/fastapi/issues/1515#issuecomment-782835977
These lines just needed to be added after the child of ObjectID class. An example is given in the following link.
https://github.com/tiangolo/fastapi/issues/1515#issuecomment-782838556
I had this issue until I upgraded from mongodb version 5.0.9 to version 6.0.0 so mongodb made some changes on their end to handle this if you have the ability to upgrade! I ran into this issue when creating a test server and when I created a new test server that was 6.0.0, it fixed the error.

Parse JSON MSG in Python

I am trying to parse a json MSG into a python dict.
For reference, the message is received from the Things Network with the python MQTT handler.
Here is the format I am receiving when I print the object
msg = MSG(variable_group=MSG(data0=0, data1=0, data2=0), variable2='name', variable3='num')
In its default state, I can access individual fields by msg.variable2 for example which provides 'name' but does not provide the variable name itself.
This is fine for a scenario in which I hardcode everything into my system, but I would like it to be a bit more adaptable and create new entries for variables as they come in.
Is there any way to parse this in such a way that I get both the data and the variable name?
Thanks!
EDIT:
From the input above, I would like to get a python dict containing the variable name and data.
dict =
{
variable_group : MSG(data0=0, data1=0, data2=0),
variable2 : 'name',
variable3 : 'num'
}
Currently, I can access the data via a for loop and can print the variable names if I print the entire structure, but cannot access the variable names through a looping mechanism
EDIT 2:
After doing some digging on the wrapper found the following:
def _json_object_hook(d):
return namedtuple("MSG", d.keys())(*d.values())
def json2obj(data):
return json.loads(data, object_hook=_json_object_hook)
Where the input shown above is created by passing it as 'data' to json2obj.
I am still unsure how to get a dict out of this format, haven't used object_hooks before.
From discussion in the comments below, it appears that the MSG object is a namedtuple created on the fly out of the json object.
In a case like that you can get the fields by looking at the _fields of the object. You can dict-ify a namedtuple like this
def nt_to_dict(nt):
return {field, getattr(nt, field) for field in nt._fields}
or you could just inspect the object by trolling _fields in code and using getattr as needed

How to reuse a custom pyramid json renderer from inside a called __json__ or adapter?

Using pyramid, I have a hierarchy of objects I want to dump as json.
Some of these objects are not out of the box json serializable so I either implement json or have adapter's registered to a custom json_renderer that I have registered(so I don't need to monkey patch things like datetime).
Since they are nested(e.g there's a datetime further down that hierarchy) I can't just call up json.dumps within my classes json since it's not aware of the adapters.
I've tried to read through the source, and run this through the debugger and feel like I could go and pull the renderer from the registry and fiddle about with that? But I don't think that is the intended method. Surely there is something cleaner? Unfortunately all the examples in the docs are trivial.
How can I pass back serialization to the calling custom json renderer at json_dump_using_renderer()?
def custom_json_renderer():
def datetime_adapter(obj, request):
return obj.isoformat()
json_renderer = JSON()
json_renderer.add_adapter(datetime.datetime, datetime_adapter)
class Whatever(object):
def __init__(self, item):
self.item = item
def __json__(self):
return "{ item: " + json_dump_using_renderer(obj.items) + "}"
So for starters your __json__ method should take (self, request) not just (self).. From there, you can use pyramid.renderers.render to perform a manual rendering if you want to embed a json-encoded string inside another data structure. Note that this will end up causing the item to be double-encoded but hopefully you're aware of that already.
def __json__(self, request):
return {'item': pyramid.renderers.render('json', obj.items, request=request)}
Alternatively if you don't want the data to be double-encoded then you might just be asking why the adapters do not work on sub-items of an object returned from __json__ and the answer is that the adapters are implemented using the default argument of json.dumps and it just doesn't support what you want. You'd have to find a json serialization library that does... but I'm not aware of one.

Convert Django queryset to dictionnary in a JSON serialization purpose

I'm creating an API and I need to return data in a dictionnary format sothat it can be serialized (by the API mechanism).
The code that currently works is something as simple as:
def mymethod(self):
queryset1 = MyClass.objects.get(...) # Ccontains 1 object, easy to deal with
queryset2 = OtherClass.objects.filter(...) # Contains N objects, hard to deal with !
return {
'qs1_result': queryset1.some_attribute # This works well
}
Returning data from queryset1 is easy because there is 1 object. I just pick the attribute I need and it works. Now let's say that in addition, I want to return data from queryset2, where there are many objects, and that I don't need every attributes of the object.
How would you do that?
I repeat that I do NOT need to make the serialization myself. I just need to return structured data sothat the serialization can be made.
Thanks a lot.
From the Django docs: https://docs.djangoproject.com/en/dev/topics/serialization/#subset-of-fields
Subset of fields
If you only want a subset of fields to be serialized, you can specify a fields argument to the serializer:
from django.core import serializers
data = serializers.serialize('json', SomeModel.objects.all(), fields=('name','size'))
In this example, only the name and size attributes of each model will be serialized.

Python model object validation

I'm writing an interface to be used by two applications. This interface should use some DoSomethingRequest and DoSomethingResponse classes to do the communication.
Is there any library that does some model validation, for example like Django's Model?
I basically want to be able to say something like:
Object A must have a "text" property of type str(), a "number" property of type int(), an "items" property of type list(). In a DRY way.
I'm looking for something like the following, or better:
class MyEmbeddedModelClass(EmbeddedModel):
text = TextField(required = True)
class MyModel(Model):
text = TextField(required = True)
number = IntField(default = 0)
items = ListField(EmbeddedModel)
a = MyModel()
a.text = "aaaa"
a.number = 1
a.items = [
MyEmbeddedModelClass("bbbb"),
MyEmbeddedModelClass("cccc"),
MyEmbeddedModelClass("dddd")
]
a.validate()
I know I can write my own, but I'd rather use a library if available, I'm a bit new to this.
If you want to enforce interfaces, or use design-by-contract, then you probably want the zope.interface library. Despite the name, which reflects its origins in Zope, it's not actually tied to that framework at all and is quite usable outside.
I think decorators could be used for this.
check this link
Combining Descriptors with Class Decorators for Validation
For a different approach check Duck typing
Because python is dynamic, the convention is to require an object to behave like an instance of a particular class rather than enforce a specific type.
Somewhere in your code, preferably at the point where you need to access those properties, but as early as possible assert that the object has those properties and further assert that those properties are what you expect them to be.
This raises an AssertionError exception if the object o, regardless of type, if it is missing the 'someattribute' attribute:
assert(hasattr(o, 'someattribute'))
Further, if o.someattribute is not a string:
assert(isinstance(o.someattribute, basestring))

Categories