Can you mix Swagger's parameters in query and in body? - python

I am getting errors when i am trying it, but i wanted to create an endpoint which accepts 2 query params and 1 body item, a list of names. When I run it in connexion but says it is an invalid specification.
/devices/list:
post:
tags: [Devices]
operationId: app.get_devices
summary: Gets a complete list of devices.
parameters:
- $ref: '#/parameters/foo-t'
- $ref: '#/parameters/bar-t'
- in: body
name: device_names
required: true
type: array
items:
type: string
description: a list of devices
...
It compiles and runs without the - in: body section. So i know the 2 parameters are good. It seems though I am having issue applying sending a json array to python.
Explicitly Returned error is:
connexion.exceptions.InvalidSpecification: {'in': 'body', 'name':
'device_names', 'required': True, 'type': 'array', 'items': {'type':
'string'}, 'description': 'A list of Device Names'} is not valid under
any of the given schemas
Failed validating 'oneOf' in
schema['properties']['paths']['patternProperties']['^/']['properties']['post']['properties']['parameters']['items']:
{'oneOf': [{'$ref': '#/definitions/parameter'},
{'$ref': '#/definitions/jsonReference'}]}
On instance['paths']['/devices/list']['post']['parameters'][2]:
{'description': 'A list of Device Names',
'in': 'body',
'items': {'type': 'string'},
'name': 'device_names',
'required': True,
'type': 'array'}
My desired endstate is that I can say:
//In javascript
$.post("devices/list", {device_names: ["a","b","c"]}, {params:{foo:1, bar:42}}).success( x => {
//...
});
# In Python3
def get_devices(foo, bar, device_names):
pass

Yes, you can mix query and body parameters.
The error is caused by incorrect syntax of the body parameter. Change it so that type and items are wrapped into schema, like this:
- in: body
name: device_names
required: true
schema: # <-------
type: array
items:
type: string
description: a list of devices
In OpenAPI 2.0, non-body parameters (path, query, header, form params) use the type keyword directly, but body parameters must have their type wrapped into schema.
The example above matches a request body that contains a string array as is – ["a", "b", "c"].
If the array is supposed to be wrapped into a JSON object
{
"device_names": ["a", "b", "c"]
}
you need to change the body parameter as follows:
- in: body
name: device_names
required: true
schema:
type: object
required: [device_names]
properties:
device_names:
type: array
items:
type: string
description: a list of devices

Related

Pydantic list of dictionaries converted to single dict with its keys

I have following pydantic base model:
from typing import Dict, List, Optional, Union
from pydantic import BaseModel
class WSMessage(BaseModel):
action: str
success: Optional[bool] = None
sent_from: Optional[str] = None
send_to: Optional[str] = None
data: Optional[Union[str, Dict, List]] = None
msg: Optional[Union[str, Dict, List]] = None
reason: Optional[Union[str, Dict, List]] = None
class Config:
extra = "allow"
And the following data:
data = {
'action': 'reply',
'sent_from': 'master',
'send_to': '192.168.0.100_UE4yWw69iSBEf67JhhWTpg==',
'data': None,
'success': True,
'msg': [
{'name': 'entry1_name', 'value': 'entry1_value'},
{'name': 'entry2_name', 'value': 'entry2_value'}
],
'reason': None,
'to_action': 'get_system_properties',
'completed': True,
}
However when I try to load the values into pydantic model, data['msg'] is translated to a single dict instead of list of dicts.
>>> msg = WSMessage(**data)
>>> msg
WSMessage(
action='reply',
success=True,
sent_from='jumphost',
send_to='46.235.96.113_UE4yWw69iSBEf67JhhWTpg==',
data=None,
msg={'name': 'value'},
reason=None,
completed=True,
to_action='get_system_properties'
)
>>> msg.msg
{'name': 'value'}
What am I doing wrong? I want msg to accept any form of data. Or more specifically, string, dict or list.
If I remove 'msg' from my model, it will properly parse it to list of dict.
Your code almost works. First, you should use List[dict] over List since it is more precise. Second, when you use a Union to define a field, pydantic will match in the order of the union (first matching data structure).
As your code is written:
msg: Optional[Union[str, Dict, List[Dict]] = None
Given a list of dictionaries, pydantic will try to coerce your value to a dict (before attempting a list of dict) – since the first object in your list is a dictionary, it can successfully coerce it and it completes.
If you switch the order of the union:
msg: Optional[Union[str, List[Dict], Dict]] = None
Pydantic will now first check if the value is a list of dictionaries, before resolving to match a dictionary. This should now work.
Relevantly: Discriminated unions are an oft debated subject in pydantic:
https://github.com/pydantic/pydantic/issues/619
https://github.com/pydantic/pydantic/issues/4675

Pydantic: how to parse non dict objects

The following data is input
data = {
'campaigns': [
{
'title': 'GBP',
'geo_segment': 'WW',
'ac_type': 'Value',
'conversion': 'soft',
'asset_type': 'ALL',
'date': '22.04.21',
'name': 'GBP_WW_1_core_22.04.21',
'budget': '2000',
'cpa': '1,00'
}
],
'stages': [
'pre',
'post'
],
'language_mode': 'all_en'
}
To parse campaigns, I use the parse_obj() method
campaigns = parse_obj_as(List[CampaignData], data['campaigns'])
class CampaignData(BaseModel):
title: NonEmptyString
geo_segment: NonEmptyString
......
It works.
How to validate the rest of the data (stages: List, language_mode: str), which is not of type dict?
class GoogleCheckCampaignStages(BaseModel):
stages: List[str]
class GoogleCheckLanguageMode(BaseModel):
language_mode: str
If I run
stages = parse_obj_as(List[GoogleCheckCampaignStages], data['stages'])
returns
value is not a valid dict (type=type_error.dict)
Same result with data['language_mode'].
If I try with parse_raw_as() method
parse_raw_as(GoogleCheckLanguageMode, data['language_mode'])
returns
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
So how to parse str and list values?
The error you are encountering is because you are passing in data["stages"] which is just a list/array. It has no key called stages and therefore Pydantic doesn't know how to assign it.
Assuming that NonEmptyString is defined as below, I would suggest creating one model that processes the whole data object, for example like this:
from pydantic import BaseModel, parse_obj_as, constr
from typing import List
NonEmptyString = constr(min_length=1)
class CampaignData(BaseModel):
title: NonEmptyString
geo_segment: NonEmptyString
# and so on ...
class Data(BaseModel):
campaigns: List[CampaignData]
stages: List[str]
language_mode: str
parsed_data = parse_obj_as(Data, data)
print(parsed_data)
# campaigns=[CampaignData(title='GBP', geo_segment='WW', ...)] stages=['pre', 'post'] language_mode='all_en'
If you'd like to access only specific elements, you can easily do it like this:
print(parsed_data.stages)
# ['pre', 'post']

TypeError: string indices must be integers - Python JSON

Getting TypeError: string indices must be integers on the my_object instantiation here below (3rd line of method)
def get_note_retrieval_body(event):
sns_body = event["Records"][0]["Sns"]
message = json.loads(sns_body["Message"])
my_object = message["data"]["getNotes"]
return my_object
I get the following (account numbers etc are marked with XXX) when i use str(event) and then json format it, so this will tell you what the event looks like
{
'Records': [{
'EventSource': 'aws:sns',
'EventVersion': '1.0',
'EventSubscriptionArn': 'arn:aws:sns:us-east-1:XXXXXX:topic-name-sandbox:7XXXX',
'Sns': {
'Type': 'Notification',
'MessageId': 'd1074c88-ae21-52b6-8a75-1b07d766cfdd',
'TopicArn': 'arn:aws:sns:us-east-1:XXXXXXX:topic-name',
'Subject': None,
'Message': '"{\\"data\\": {\\"getNotes\\": {\\"claimNumber\\": \\"AAAB09000010\\", \\"dateEntered\\": \\"2010-04-22T08:03:53\\",\\"categoryCode\\": \\"fdf49\\",\\"subCategoryCode\\": \\"ATT\\", \\"fileNoteTextDetails\\": [{\\"fileNoteText\\": {\\"fileNoteID\\": \\"112B40FE42934055\\", \\"noteText\\": \\"Send Acknowledgement Letter to Claimant\\", \\"authorID\\": \\"0\\"}, \\"fileNoteAttachments\\": [{\\"attachment\\": {\\"fileName\\": \\"F70F880879D35FC4.doc\\", \\"fileExtension\\": \\".URL\\", \\"dateCreated\\": \\"2010-04-22T08:59:57\\", \\"createdBy\\": \\"CLONER\\", \\"dateUpdated\\": \\"2020-07-30T08:36:19.1903051\\", \\"updatedBy\\": \\"EVERYONE\\"}}]}], \\"fileNoteExtendedEntityData\\": {\\"dateOnDocument\\": \\"2010-04-22T08:59:57\\", \\"serviceDateFrom\\": \\"2010-04-22T08:59:57\\", \\"serviceDateThrough\\": \\"2010-04-22T08:59:57\\", \\"author\\": \\"n0000000\\"}}}}"',
'Timestamp': '2020-07-20T10:50:47.850Z',
'SignatureVersion': '1',
'Signature': 'XXXXXX',
'SigningCertUrl': 'https://sns.us-east-1.amazonaws.com/XXXcert.pem',
'UnsubscribeUrl': 'https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:XXXXXX:topic-name-sandbox:7XX'.
'MessageAttributes': {}
}
}]
}
When you run json.loads on sns_body["Message"], you still get back a string. You can run json.loads twice, and that should solve the issue.
sns_body["Message"] is quoted twice (i.e., it is wrapped in single quotes and double quotes). So when you try to decode it once, you still get back a string, but this time it is only quoted once. Then a second json.loads will decode the string into a dictionary.
def get_note_retrieval_body(event):
sns_body = event["Records"][0]["Sns"]
message = json.loads(json.loads(sns_body["Message"]))
my_object = message["data"]["getNotes"]
return my_object

I need to parse and store list of values from json or yaml file

I need to parse few of values from the provided yaml or json file. Below is the content from my yaml file,
swagger: '2.0'
info:
description: >-
This is a sample server Petstore server. You can find out more about
Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net,
#swagger](http://swagger.io/irc/). For this sample, you can use the api
key `special-key` to test the authorization filters.
version: 1.0.0
title: Swagger Petstore
termsOfService: 'http://swagger.io/terms/'
contact:
email: apiteam#swagger.io
license:
name: Apache 2.0
url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
host: petstore.swagger.io
basePath: /v2
tags:
- name: pet
description: Everything about your Pets
externalDocs:
description: Find out more
url: 'http://swagger.io'
- name: store
description: Access to Petstore orders
- name: user
description: Operations about user
externalDocs:
description: Find out more about our store
url: 'http://swagger.io'
schemes:
- https
- http
paths:
/pet:
post:
tags:
- pet
summary: Add a new pet to the store
description: ''
operationId: addPet
consumes:
- application/json
- application/xml
produces:
- application/xml
- application/json
parameters:
- in: body
name: body
description: Pet object that needs to be added to the store
required: true
schema:
$ref: '#/definitions/Pet'
responses:
'405':
description: Invalid input
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
put:
tags:
- pet
summary: Update an existing pet
description: ''
operationId: updatePet
consumes:
- application/json
- application/xml
produces:
- application/xml
- application/json
parameters:
- in: body
name: body
description: Pet object that needs to be added to the store
required: true
schema:
$ref: '#/definitions/Pet'
responses:
'400':
description: Invalid ID supplied
'404':
description: Pet not found
'405':
description: Validation exception
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
/pet/findByStatus:
get:
tags:
- pet
summary: Finds Pets by status
description: Multiple status values can be provided with comma separated strings
operationId: findPetsByStatus
produces:
- application/xml
- application/json
parameters:
- name: status
in: query
description: Status values that need to be considered for filter
required: true
type: array
items:
type: string
enum:
- available
- pending
- sold
default: available
collectionFormat: multi
responses:
'200':
description: successful operation
schema:
type: array
items:
$ref: '#/definitions/Pet'
'400':
description: Invalid status value
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
/pet/findByTags:
get:
tags:
- pet
summary: Finds Pets by tags
description: >-
Muliple tags can be provided with comma separated strings. Use
tag1, tag2, tag3 for testing.
operationId: findPetsByTags
produces:
- application/xml
- application/json
parameters:
- name: tags
in: query
description: Tags to filter by
required: true
type: array
items:
type: string
collectionFormat: multi
responses:
'200':
description: successful operation
schema:
type: array
items:
$ref: '#/definitions/Pet'
'400':
description: Invalid tag value
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
deprecated: true
'/pet/{petId}':
get:
tags:
- pet
summary: Find pet by ID
description: Returns a single pet
operationId: getPetById
produces:
- application/xml
- application/json
parameters:
- name: petId
in: path
description: ID of pet to return
required: true
type: integer
format: int64
responses:
'200':
description: successful operation
schema:
$ref: '#/definitions/Pet'
'400':
description: Invalid ID supplied
'404':
description: Pet not found
security:
- api_key: []
post:
tags:
- pet
summary: Updates a pet in the store with form data
description: ''
operationId: updatePetWithForm
consumes:
- application/x-www-form-urlencoded
produces:
- application/xml
- application/json
parameters:
- name: petId
in: path
description: ID of pet that needs to be updated
required: true
type: integer
format: int64
- name: name
in: formData
description: Updated name of the pet
required: false
type: string
- name: status
in: formData
description: Updated status of the pet
required: false
type: string
responses:
'405':
description: Invalid input
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
delete:
tags:
- pet
summary: Deletes a pet
description: ''
operationId: deletePet
produces:
- application/xml
- application/json
parameters:
- name: api_key
in: header
required: false
type: string
- name: petId
in: path
description: Pet id to delete
required: true
type: integer
format: int64
responses:
'400':
description: Invalid ID supplied
'404':
description: Pet not found
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
'/pet/{petId}/uploadImage':
post:
tags:
- pet
summary: uploads an image
description: ''
operationId: uploadFile
consumes:
- multipart/form-data
produces:
- application/json
parameters:
- name: petId
in: path
description: ID of pet to update
required: true
type: integer
format: int64
- name: additionalMetadata
in: formData
description: Additional data to pass to server
required: false
type: string
- name: file
in: formData
description: file to upload
required: false
type: file
responses:
'200':
description: successful operation
schema:
$ref: '#/definitions/ApiResponse'
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
/store/inventory:
get:
tags:
- store
summary: Returns pet inventories by status
description: Returns a map of status codes to quantities
operationId: getInventory
produces:
- application/json
parameters: []
responses:
'200':
description: successful operation
schema:
type: object
additionalProperties:
type: integer
format: int32
security:
- api_key: []
/store/order:
post:
tags:
- store
summary: Place an order for a pet
description: ''
operationId: placeOrder
produces:
- application/xml
- application/json
parameters:
- in: body
name: body
description: order placed for purchasing the pet
required: true
schema:
$ref: '#/definitions/Order'
responses:
'200':
description: successful operation
schema:
$ref: '#/definitions/Order'
'400':
description: Invalid Order
'/store/order/{orderId}':
get:
tags:
- store
summary: Find purchase order by ID
description: >-
For valid response try integer IDs with value >= 1 and <= 10.
Other values will generated exceptions
operationId: getOrderById
produces:
- application/xml
- application/json
parameters:
- name: orderId
in: path
description: ID of pet that needs to be fetched
required: true
type: integer
maximum: 10
minimum: 1
format: int64
responses:
'200':
description: successful operation
schema:
$ref: '#/definitions/Order'
'400':
description: Invalid ID supplied
'404':
description: Order not found
delete:
tags:
- store
summary: Delete purchase order by ID
description: >-
For valid response try integer IDs with positive integer value.
Negative or non-integer values will generate API errors
operationId: deleteOrder
produces:
- application/xml
- application/json
parameters:
- name: orderId
in: path
description: ID of the order that needs to be deleted
required: true
type: integer
minimum: 1
format: int64
responses:
'400':
description: Invalid ID supplied
'404':
description: Order not found
/user:
post:
tags:
- user
summary: Create user
description: This can only be done by the logged in user.
operationId: createUser
produces:
- application/xml
- application/json
parameters:
- in: body
name: body
description: Created user object
required: true
schema:
$ref: '#/definitions/User'
responses:
default:
description: successful operation
/user/createWithArray:
post:
tags:
- user
summary: Creates list of users with given input array
description: ''
operationId: createUsersWithArrayInput
produces:
- application/xml
- application/json
parameters:
- in: body
name: body
description: List of user object
required: true
schema:
type: array
items:
$ref: '#/definitions/User'
responses:
default:
description: successful operation
/user/createWithList:
post:
tags:
- user
summary: Creates list of users with given input array
description: ''
operationId: createUsersWithListInput
produces:
- application/xml
- application/json
parameters:
- in: body
name: body
description: List of user object
required: true
schema:
type: array
items:
$ref: '#/definitions/User'
responses:
default:
description: successful operation
/user/login:
get:
tags:
- user
summary: Logs user into the system
description: ''
operationId: loginUser
produces:
- application/xml
- application/json
parameters:
- name: username
in: query
description: The user name for login
required: true
type: string
- name: password
in: query
description: The password for login in clear text
required: true
type: string
responses:
'200':
description: successful operation
schema:
type: string
headers:
X-Rate-Limit:
type: integer
format: int32
description: calls per hour allowed by the user
X-Expires-After:
type: string
format: date-time
description: date in UTC when token expires
'400':
description: Invalid username/password supplied
/user/logout:
get:
tags:
- user
summary: Logs out current logged in user session
description: ''
operationId: logoutUser
produces:
- application/xml
- application/json
parameters: []
responses:
default:
description: successful operation
'/user/{username}':
get:
tags:
- user
summary: Get user by user name
description: ''
operationId: getUserByName
produces:
- application/xml
- application/json
parameters:
- name: username
in: path
description: 'The name that needs to be fetched. Use user1 for testing. '
required: true
type: string
responses:
'200':
description: successful operation
schema:
$ref: '#/definitions/User'
'400':
description: Invalid username supplied
'404':
description: User not found
put:
tags:
- user
summary: Updated user
description: This can only be done by the logged in user.
operationId: updateUser
produces:
- application/xml
- application/json
parameters:
- name: username
in: path
description: name that need to be updated
required: true
type: string
- in: body
name: body
description: Updated user object
required: true
schema:
$ref: '#/definitions/User'
responses:
'400':
description: Invalid user supplied
'404':
description: User not found
delete:
tags:
- user
summary: Delete user
description: This can only be done by the logged in user.
operationId: deleteUser
produces:
- application/xml
- application/json
parameters:
- name: username
in: path
description: The name that needs to be deleted
required: true
type: string
responses:
'400':
description: Invalid username supplied
'404':
description: User not found
securityDefinitions:
petstore_auth:
type: oauth2
authorizationUrl: 'http://petstore.swagger.io/oauth/dialog'
flow: implicit
scopes:
'write:pets': modify pets in your account
'read:pets': read your pets
api_key:
type: apiKey
name: api_key
in: header
definitions:
Order:
type: object
properties:
id:
type: integer
format: int64
petId:
type: integer
format: int64
quantity:
type: integer
format: int32
shipDate:
type: string
format: date-time
status:
type: string
description: Order Status
enum:
- placed
- approved
- delivered
complete:
type: boolean
default: false
xml:
name: Order
Category:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
xml:
name: Category
User:
type: object
properties:
id:
type: integer
format: int64
username:
type: string
firstName:
type: string
lastName:
type: string
email:
type: string
password:
type: string
phone:
type: string
userStatus:
type: integer
format: int32
description: User Status
xml:
name: User
Tag:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
xml:
name: Tag
Pet:
type: object
required:
- name
- photoUrls
properties:
id:
type: integer
format: int64
category:
$ref: '#/definitions/Category'
name:
type: string
example: doggie
photoUrls:
type: array
xml:
name: photoUrl
wrapped: true
items:
type: string
tags:
type: array
xml:
name: tag
wrapped: true
items:
$ref: '#/definitions/Tag'
status:
type: string
description: pet status in the store
enum:
- available
- pending
- sold
xml:
name: Pet
ApiResponse:
type: object
properties:
code:
type: integer
format: int32
type:
type: string
message:
type: string
externalDocs:
description: Find out more about Swagger
url: 'http://swagger.io'
I have written the below code to extract all the API endpoints (/pets, /pets/{petID}, ...) and the API type (GET, PUT, POST, etc,.).
import yaml
import json
with open("swagger.yaml", 'r') as yaml_in, open("examplepets.json", "w") as json_out:
yaml_object = yaml.safe_load(yaml_in) # yaml_object will be a list or a dict - Converts the
json.dump(yaml_object, json_out, indent=2)
with open("examplepets.json", "r") as reading:
data = json.load(reading)
for path, values in data['paths'].items():
print(path.replace('{', '${')) # If required used print statement
for value in values:
print(value) # If required use print statement
I need to elaborate the code further to fetch the below values from swagger file, Values under the key "consumes:", "produces:"
Under "Parameters:" i need to fetch values of the key -> "name", "in", "required", "Type" Values under the below key listed keys should be extracted and printed along with the corresponding API endpoints, API method type,
"consumes:", "produces:"
"Parameters:" i need to fetch values of the key -> "name", "in", "required", "Type"
NOTE: i have already presented the code to fetch the API endpoints and API method type.
Try this,
import yaml
import json
with open("./test.yaml", 'r') as yaml_in, open("yml_test.json", "w") as json_out:
data = json.loads(json.dumps(yaml.load(yaml_in, Loader=yaml.FullLoader)))
output_dict = {}
for url in data["paths"]:
for method in data["paths"][url]:
output_dict[url + "/" + method] = {}
output_dict[url + "/" + method]["parameters"] = {}
if "consumes" in data["paths"][url][method]:
output_dict[url+"/"+method]["consumes"] = data["paths"][url][method]["consumes"]
if "produces" in data["paths"][url][method]:
output_dict[url+"/"+method]["produces"] = data["paths"][url][method]["produces"]
if data["paths"][url][method]["parameters"]:
if "in" in data["paths"][url][method]["parameters"][0]:
output_dict[url+"/"+method]["parameters"]["in"] = data["paths"][url][method]["parameters"][0]["in"]
if "name" in data["paths"][url][method]["parameters"][0]:
output_dict[url+"/"+method]["parameters"]["name"] = data["paths"][url][method]["parameters"][0]["name"]
if "required" in data["paths"][url][method]["parameters"][0]:
output_dict[url+"/"+method]["parameters"]["required"] = data["paths"][url][method]["parameters"][0]["required"]
if "type" in data["paths"][url][method]["parameters"][0]:
output_dict[url+"/"+method]["parameters"]["type"] = data["paths"][url][method]["parameters"][0]["type"]
json.dump(output_dict, json_out)
The OutPut shows below and saves the same to yml_test.json file.
{'/pet/post': {'parameters': {'in': 'body', 'name': 'body', 'required': True}, 'consumes': ['application/json', 'application/xml'], 'produces': ['application/xml', 'application/json']}, '/pet/put': {'parameters': {'in': 'body', 'name': 'body', 'required': True}, 'consumes': ['application/json', 'application/xml'], 'produces': ['application/xml', 'application/json']}, '/pet/findByStatus/get': {'parameters': {'in': 'query', 'name': 'status', 'required': True, 'type': 'array'}, 'produces': ['application/xml', 'application/json']}, '/pet/findByTags/get': {'parameters': {'in': 'query', 'name': 'tags', 'required': True, 'type': 'array'}, 'produces': ['application/xml', 'application/json']}, '/pet/{petId}/get': {'parameters': {'in': 'path', 'name': 'petId', 'required': True, 'type': 'integer'}, 'produces': ['application/xml', 'application/json']}, '/pet/{petId}/post': {'parameters': {'in': 'path', 'name': 'petId', 'required': True, 'type': 'integer'}, 'consumes': ['application/x-www-form-urlencoded'], 'produces': ['application/xml', 'application/json']}, '/pet/{petId}/delete': {'parameters': {'in': 'header', 'name': 'api_key', 'required': False, 'type': 'string'}, 'produces': ['application/xml', 'application/json']}, '/pet/{petId}/uploadImage/post': {'parameters': {'in': 'path', 'name': 'petId', 'required': True, 'type': 'integer'}, 'consumes': ['multipart/form-data'], 'produces': ['application/json']}, '/store/inventory/get': {'parameters': {}, 'produces': ['application/json']}, '/store/order/post': {'parameters': {'in': 'body', 'name': 'body', 'required': True}, 'produces': ['application/xml', 'application/json']}, '/store/order/{orderId}/get': {'parameters': {'in': 'path', 'name': 'orderId', 'required': True, 'type': 'integer'}, 'produces': ['application/xml', 'application/json']}, '/store/order/{orderId}/delete': {'parameters': {'in': 'path', 'name': 'orderId', 'required': True, 'type': 'integer'}, 'produces': ['application/xml', 'application/json']}, '/user/post': {'parameters': {'in': 'body', 'name': 'body', 'required': True}, 'produces': ['application/xml', 'application/json']}, '/user/createWithArray/post': {'parameters': {'in': 'body', 'name': 'body', 'required': True}, 'produces': ['application/xml', 'application/json']}, '/user/createWithList/post': {'parameters': {'in': 'body', 'name': 'body', 'required': True}, 'produces': ['application/xml', 'application/json']}, '/user/login/get': {'parameters': {'in': 'query', 'name': 'username', 'required': True, 'type': 'string'}, 'produces': ['application/xml', 'application/json']}, '/user/logout/get': {'parameters': {}, 'produces': ['application/xml', 'application/json']}, '/user/{username}/get': {'parameters': {'in': 'path', 'name': 'username', 'required': True, 'type': 'string'}, 'produces': ['application/xml', 'application/json']}, '/user/{username}/put': {'parameters': {'in': 'path', 'name': 'username', 'required': True, 'type': 'string'}, 'produces': ['application/xml', 'application/json']}, '/user/{username}/delete': {'parameters': {'in': 'path', 'name': 'username', 'required': True, 'type': 'string'}, 'produces': ['application/xml', 'application/json']}}

String indices must be integers - Django

I have a pretty big dictionary which looks like this:
{
'startIndex': 1,
'username': 'myemail#gmail.com',
'items': [{
'id': '67022006',
'name': 'Adopt-a-Hydrant',
'kind': 'analytics#accountSummary',
'webProperties': [{
'id': 'UA-67522226-1',
'name': 'Adopt-a-Hydrant',
'websiteUrl': 'https://www.udemy.com/,
'internalWebPropertyId': '104343473',
'profiles': [{
'id': '108333146',
'name': 'Adopt a Hydrant (Udemy)',
'type': 'WEB',
'kind': 'analytics#profileSummary'
}, {
'id': '132099908',
'name': 'Unfiltered view',
'type': 'WEB',
'kind': 'analytics#profileSummary'
}],
'level': 'STANDARD',
'kind': 'analytics#webPropertySummary'
}]
}, {
'id': '44222959',
'name': 'A223n',
'kind': 'analytics#accountSummary',
And so on....
When I copy this dictionary on my Jupyter notebook and I run the exact same function I run on my django code it runs as expected, everything is literarily the same, in my django code I'm even printing the dictionary out then I copy it to the notebook and run it and I get what I'm expecting.
Just for more info this is the function:
google_profile = gp.google_profile # Get google_profile from DB
print(google_profile)
all_properties = []
for properties in google_profile['items']:
all_properties.append(properties)
site_selection=[]
for single_property in all_properties:
single_propery_name=single_property['name']
for single_view in single_property['webProperties'][0]['profiles']:
single_view_id = single_view['id']
single_view_name = (single_view['name'])
selections = single_propery_name + ' (View: '+single_view_name+' ID: '+single_view_id+')'
site_selection.append(selections)
print (site_selection)
So my guess is that my notebook has some sort of json parser installed or something like that? Is that possible? Why in django I can't access dictionaries the same way I can on my ipython notebooks?
EDITS
More info:
The error is at the line: for properties in google_profile['items']:
Django debug is: TypeError at /gconnect/ string indices must be integers
Local Vars are:
all_properties =[]
current_user = 'myemail#gmail.com'
google_profile = `the above dictionary`
So just to make it clear for who finds this question:
If you save a dictionary in a database django will save it as a string, so you won't be able to access it after.
To solve this you can re-convert it to a dictionary:
The answer from this post worked perfectly for me, in other words:
import json
s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
json_acceptable_string = s.replace("'", "\"")
d = json.loads(json_acceptable_string)
# d = {u'muffin': u'lolz', u'foo': u'kitty'}
There are many ways to convert a string to a dictionary, this is only one. If you stumbled in this problem you can quickly check if it's a string instead of a dictionary with:
print(type(var))
In my case I had:
<class 'str'>
before converting it with the above method and then I got
<class 'dict'>
and everything worked as supposed to

Categories

Resources