Modèles de données

  • La construction d'un modèle de données pour vos services API tourne autour de l'utilisation des dataclasses intégrées de Python.
  • les dataclasses vous permettent de définir vos modèles d'une manière déclarative qui vous permet de les intégrer à votre IDE pour la complétion ou la vérification de type.
  • En outre, Zato étend les dataclasses pour prendre en charge l'auto-sérialisation à partir de et vers les dictionnaires Python, JSON et les définitions OpenAPI.
  • Tout comme les services, les modèles peuvent être déployés à chaud sur les serveurs Zato sans aucun redémarrage.
  • Les modèles sont réutilisables à travers les services ou les systèmes - ils ne sont pas spécifiques à REST seulement.

Utilisation typique

  • Chaque objet de requête et de réponse est une classe de données sous-classant une classe Model.
  • Dans votre code, vous ne travaillez qu'avec des objets métier de haut niveau tels que GetClientRequest et GetClientResponse ci-dessous.
  • Zato sérialise automatiquement les objets depuis et vers JSON, des dictionnaires Python ou des définitions OpenAPI.
# -*- coding: utf-8 -*-

# stdlib
from dataclasses import dataclass

# Zato
from zato.server.service import Model, Service

# ###########################################################################

@dataclass(init=False)
class GetClientRequest(Model):
    client_id: int

@dataclass(init=False)
class GetClientResponse(Model):
    name:    str
    email:   str
    segment: str

# ###########################################################################

class GetClient(Service):

    class SimpleIO:
        input  = GetClientRequest
        output = GetClientResponse

    def handle(self):

        # Enable type checking and type completion
        request = self.request.input # type: GetClientRequest

        # Log details of our request
        self.logger.info('Processing client `%s`', request.client_id)

        # Produce our response - in a full service this information
        # will be obtained from one or more databases or systems.
        response = GetClientResponse()
        response.name    = 'Jane Doe'
        response.email   = 'hello@example.com'
        response.segment = 'RNZ'

        # Return the response to our caller
        self.response.payload = response

# ###########################################################################

Invoquons-le:

$ curl http://pubapi:<password>@localhost:17010/zato/api/invoke/client.get-client \
    -d '{"client_id":123}' ; echo
{"name":"Jane Doe","email":"hello@example.com","segment":"RNZ"}
$

Travailler avec des listes

  • Dans l'exemple ci-dessous, nous retournons une liste d'objets.
  • Notez que Phone est une classe de données ordinaire qui n'est pas utilisée directement comme une demande ou une réponse de haut niveau, ce qui signifie qu'elle n'a pas besoin de sous-classer la classe Model.
  • Les classes de données peuvent être imbriquées dans d'autres classes de données, formant ainsi des hiérarchies arbitraires d'objets dans un modèle de données.
# -*- coding: utf-8 -*-

# stdlib
from dataclasses import dataclass

# Zato
from zato.common.typing_ import list_
from zato.server.service import Model, Service

# ###########################################################################

@dataclass(init=False)
class Phone(Model):
    imei:       str
    owner_id:   int
    owner_name: str

# ###########################################################################

@dataclass(init=False)
class GetPhoneListRequest(Model):
    client_id: int

@dataclass(init=False)
class GetPhoneListResponse(Model):
    phone_list:    list_[Phone]
    response_type: str

# ###########################################################################

class GetPhoneDetails(Service):

    class SimpleIO:
        input  = GetPhoneListRequest
        output = GetPhoneListResponse

    def handle(self):

        # Enable type checking and type completion
        request = self.request.input # type: GetPhoneListRequest

        # Log details of our request
        self.logger.info('Processing client `%s`', request.client_id)

        # Build our response now - in a full service this information
        # would be read from an exteran system or database.

        # Our list of phones to return
        phone_list = []

        # Build the fist phone ..
        phone1 = Phone()
        phone1.imei = '123'
        phone1.owner_id = 456
        phone1.owner_name = 'John Doe'

        # .. the second one ..
        phone2 = Phone()
        phone2.imei = '789'
        phone2.owner_id = 999
        phone2.owner_name = 'Jane Doe'

        # .. populate the container for phones tha we return ..
        phone_list.append(phone1)
        phone_list.append(phone2)

        # .. build the top-level response element ..
        response = GetPhoneListResponse()
        response.response_type = 'RZH'
        response.phone_list = phone_list

        # .. and return the response to our caller
        self.response.payload = response

# ###########################################################################

Nous pouvons l'invoquer maintenant avec:

$ curl http://pubapi:<password>@localhost:17010/zato/api/invoke/phone.get-phone-list \
    -d '{"client_id":789}'
{"response_type":"RZH",
 "phone_list": [
    {"imei":"123","owner_id":456,"owner_name":"John Doe"},
    {"imei":"789","owner_id":999,"owner_name":"Jane Doe"}]}
$

Sujets connexes