Troubles with validating nested values - python

I am looking to add validation to my api endpoint using Marshmallow.
I am running into the problem of how to get this chunk properly validated. The end goal is to make sure impressions is a positive number.
I would greatly appreciate any help or insight you can provide. First time using Marshmallow.
Sample Json:
{
"mode": [
{
"type": "String",
"values": {
"visits": 1000,
"budget": 400
},
"active": true
}
]
}
Sample code attempting to validate
class ValidateValues(BaseSchema):
visits = fields.Int(allow_none=True, validate=[validate.Range(min=0, error="Value must be greater than 0")])
budget = fields.Int(allow_none=True, validate=[validate.Range(min=0, error="Value must be greater than 0")])
class ModeSchema(BaseSchema):
type = fields.String(required=True)
active = fields.Boolean(required=True)
values = fields.Nested(ValidateValues)
class JsonSchema(BaseSchema):
mode = fields.List(fields.Dict(fields.Nested(ModeSchema, many=True)))
Current result
{
"mode": {
"0": {
"type": {
"key": [
"Invalid type."
]
},
"values": {
"key": [
"Invalid type."
]
},
"active": {
"key": [
"Invalid type."
]
}
}
}
}

You're just using a list of Nested fields. No need for Dict, here.
And no need for many=True since you're putting the Nested field in a List field.
Try this:
class JsonSchema(BaseSchema):
mode = fields.List(fields.Nested(ModeSchema))

Related

python django serializer wrong date time format for DateTimeField

I'm using Django 3.0.2.
I have a serializer defined:
class ValueNestedSerializer(request_serializer.Serializer):
lower = request_serializer.DateTimeField(required=True, allow_null=False, format=None, input_formats=['%Y-%m-%dT%H:%M:%SZ',])
upper = request_serializer.DateTimeField(required=True, allow_null=False, format=None, input_formats=['%Y-%m-%dT%H:%M:%SZ',])
class DateRangeSerializer(request_serializer.Serializer):
attribute = request_serializer.CharField(default="UPLOAD_TIME")
operator = request_serializer.CharField(default="between_dates")
value = ValueNestedSerializer(required=True)
timezone = request_serializer.CharField(default="UTC")
timezoneOffset = request_serializer.IntegerField(default=0)
class BaseQueryPayload(request_serializer.Serializer):
appid = request_serializer.CharField(required=True, validators=[is_valid_appid])
filters = request_serializer.ListField(
required=True, validators=[is_validate_filters],
min_length=1
)
date_range = DateRangeSerializer(required=True)
And the payload :
{
"appid": "6017cef554df4124274ef36d",
"filters": [
{
"table": "session",
"label": "1month"
}
],
"date_range": {
"value": {
"lower": "2023-01-01T01:00:98Z",
"upper": "2023-01-20T01:00:98Z"
}
},
"page": 1
}
But I get this validation error:
{
"error": {
"date_range": {
"value": {
"lower": [
"Datetime has wrong format. Use one of these formats instead: YYYY-MM-DDThh:mm:ssZ."
],
"upper": [
"Datetime has wrong format. Use one of these formats instead: YYYY-MM-DDThh:mm:ssZ."
]
}
}
}
}
The suggested format YYYY-MM-DDThh:mm:ssZ is similar to what is passed.
Am I missing anything here?
Format is wrong because seconds must be in 0-59 range (while you try to post 98s)

check if a property contains a specific value in a document with pymongo

I have a collection of documents that looks like this
{
"_id": "4",
"contacts": [
{
"email": "mail#mail.com",
"name": "A1",
"phone": "00",
"crashNotificationEnabled": false,
"locationShared": true,
"creationDate": ISODate("2020-10-19T15:19:04.498Z")
},
{
"email": "mail#mail.com",
"name": "AG2",
"phone": "00",
"crashNotificationEnabled": false,
"locationShared": false,
"creationDate": ISODate("2020-10-19T15:19:04.498Z")
}
],
"creationDate": ISODate("2020-10-19T15:19:04.498Z"),
"_class": ".model.UserContacts"
}
And i would like to iterate through all documents to check if either crashNotificationEnabled or locationShared is true and add +1 to a counter if its the case, im quite new to python and mongosql so i actually have a hard time trying to do that, i tried a lot of things but there is my last try :
def users_with_guardian_angel(mongoclient):
try:
mydb = mongoclient["main"]
userContacts = mydb["userContacts"]
users = userContacts.find()
for user in users:
result = userContacts.find_one({contacts : { $in: [true]}})
if result:
count_users = count_users + 1
print(f"{count_users} have at least one notificiation enabled")
But the result variable stays empty all the time, so if somebody could help me to accomplish what i want to do and tell what i did wrong here ?
Thanks !
Here's one way you could do it by letting the MongoDB server do all the work.
N.B.: This doesn't consider the possibility of multiple entries of the same user.
db.userContacts.aggregate([
{
"$unwind": "$contacts"
},
{
"$match": {
"$expr": {
"$or": [
"$contacts.crashNotificationEnabled",
"$contacts.locationShared"
]
}
}
},
{
"$count": "userCountWithNotificationsEnabled"
}
])
Try it on mongoplayground.net.
Example output:
[
{
"userCountWithNotificationsEnabled": 436
}
]

Extracting fields from a json file

I am provided with the following json file.
{
"results": [
{
"id": "1234",
"useless_field1": null,
"useless_field2": null,
"data": [
{
"type": "type_1",
"useless_field3": null,
"volumne": "5"
}
]
}
]
}
I would like to extract only the following fields: id, type, volume. I did it in the following way.
def extract(json_response):
return [{
item['id'],
item['data'][0]['type'],
item['data'][0]['volume']
} for item in json_response['results']]
It is possible for the type to be a list. Is my solution efficient? Are there any alternatives of solving such problems?

Getting items from an api using django

I am trying to get the amount value from the available field when I retrieve a blance from Stripe. I have the following response:
{
"available": [
{
"amount": 10302,
"currency": "cad",
"source_types": {
"card": 10302
}
}
],
"livemode": false,
"object": "balance",
"pending": [
{
"amount": 0,
"currency": "cad",
"source_types": {
"card": 0
}
}
]
}
I am trying to get the available amount, so I wrote the following:
available = balance['available']
as a response I am getting the following:
[<StripeObject at 0x110d45a98> JSON: {
"amount": 10302,
"currency": "cad",
"source_types": {
"card": 10302
}
}]
But how can I get access to the 'amount' part?
I tried:
amount = available['amount']
So I am receiving:
TypeError at /en/accounts/profile/
list indices must be integers or slices, not str
as an error.
balance['available'] contains a dictionary ({}) inside of a list ([]). Therefore, the dictionary is stored as the first element of the list, and has to be accessed using available[0]. You can get the value that corresponds to the 'amount' key by typing available[0]['amount'].

Issues decoding Collections+JSON in Python

I've been trying to decode a JSON response in Collections+JSON format using Python for a while now but I can't seem to overcome a small issue.
First of all, here is the JSON response:
{
"collection": {
"href": "http://localhost:8000/social/messages-api/",
"items": [
{
"data": [
{
"name": "messageID",
"value": 19
},
{
"name": "author",
"value": "mike"
},
{
"name": "recipient",
"value": "dan"
},
{
"name": "pm",
"value": "0"
},
{
"name": "time",
"value": "2015-03-31T15:04:01.165060Z"
},
{
"name": "text",
"value": "first message"
}
]
}
],
"version": "1.0",
"links": []
}
}
And here is how I am attempting to extract data:
response = urllib2.urlopen('myurl')
responseData = response.read()
jsonData = json.loads(responseData)
test = jsonData['collection']['items']['data']
When I run this code I get the error:
list indices must be integers, not str
If I use an integer, e.g. 0, instead of a string it merely shows 'data' instead of any useful information, unlike if I were to simply output 'items'. Similarly, I can't seem to access the data within a data child, for example:
test = jsonData['collection']['items'][0]['name']
This will argue that there is no element called 'name'.
What is the proper method of accessing JSON data in this situation? I would also like to iterate over the collection, if that helps.
I'm aware of a package that can be used to simplify working with Collections+JSON in Python, collection-json, but I'd rather be able to do this without using such a package.

Categories

Resources