Pydantic: How to use pydantic to extract single field in dict?

Created on 15 Nov 2019  路  4Comments  路  Source: samuelcolvin/pydantic

Question

Here's a dict I got from API json:

{'type': 'message', 'id': 'StringID', 'timestamp': '2019-11-15T10:20:26.6469421Z', 'serviceUrl': 'https://service-url/', 'channelId': 'webchat', 'from': {'id': 'ID'}, 'conversation': {'id': 'AnotherID}, 'recipient': {'id': 'RecipientID', 'name': 'AppName'}, 'textFormat': 'plain', 'locale': 'en-US', 'text': 'hello', 'entities': [{'type': 'ClientCapabilities', 'requiresBotState': True, 'supportsListening': True, 'supportsTts': True}], 'channelData': {'clientActivityID': 'activityID'}}

Please complete:

  • OS: Debian Stretch (docker python:3.7)
  • Python version import sys; print(sys.version): 3.7.4
  • Pydantic version import pydantic; print(pydantic.VERSION): 0.32.2

Where possible please include a self contained code snippet describing your question:

import pydantic
from pydantic import BaseModel, Schema
class SkypeMessageModel(BaseModel):
    type: str
    id: str
    timestamp: datetime
    serviceUrl: str
    channelId: str
    recipient: str # i want to get "from.id"
   # from: dict not working because of python keyword
...
question

Most helpful comment

@kiennguyen1101
You can use validator to assign custom value to a field.
https://pydantic-docs.helpmanual.io/usage/validators/

from pydantic import BaseModel, Schema, validator


class Model(BaseModel):
    from_: str = Schema(..., alias='from')  # ... is required.

    @validator('from_', always=True, pre=True)
    def validate_from_id(cls, v):
        if not isinstance(v, dict):
            raise TypeError('"from" type must be dict')
        if 'id' not in v:
            raise ValueError('Not found "id" in "from"')
        return v['id']

exmaple_json = {'from': {'id': 'ID'}}
model = Model.parse_obj(exmaple_json)
print(model.from_)
# > ID
print(model.json(by_alias=True))  # if you want to dump json by alias then, you should add 'by_alias=True'
# > {"from": "ID"}

I implement the example with pydantic version 0.32.2 which is the previous release.
If you want to use a later version(v1.x), you should use Filed instead of Schema.

All 4 comments

I'm not quite sure what your question is. If it's related to extracting from, you should use Config.alias.

Hi, sorry for the late reply; please allow me to ask again:
With the json input: {"from": {"id": "ID"}} how do I extract only "ID" string?

@kiennguyen1101
You can use validator to assign custom value to a field.
https://pydantic-docs.helpmanual.io/usage/validators/

from pydantic import BaseModel, Schema, validator


class Model(BaseModel):
    from_: str = Schema(..., alias='from')  # ... is required.

    @validator('from_', always=True, pre=True)
    def validate_from_id(cls, v):
        if not isinstance(v, dict):
            raise TypeError('"from" type must be dict')
        if 'id' not in v:
            raise ValueError('Not found "id" in "from"')
        return v['id']

exmaple_json = {'from': {'id': 'ID'}}
model = Model.parse_obj(exmaple_json)
print(model.from_)
# > ID
print(model.json(by_alias=True))  # if you want to dump json by alias then, you should add 'by_alias=True'
# > {"from": "ID"}

I implement the example with pydantic version 0.32.2 which is the previous release.
If you want to use a later version(v1.x), you should use Filed instead of Schema.

Agreed.

Typo: Field not Filed

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sbv-trueenergy picture sbv-trueenergy  路  3Comments

mgresko picture mgresko  路  3Comments

nav picture nav  路  3Comments

krzysieqq picture krzysieqq  路  3Comments

vvoody picture vvoody  路  3Comments