JSON

Overview

As with XML, it’s most convenient to use Simple IO (SIO) to accept or return JSON in your services but if that’s not an option using JSON directly is still a piece of cake.

For starters, let’s save the code below in a json_example.py file and hot-deploy it. This will be the service we’ll be modifying in this chapter.

A channel through which it will be exposed to the outside world will also be needed. Note the channel’s data format is JSON.

1
2
3
4
5
from zato.server.service import Service

class MyService(Service):
    def handle(self):
        pass
../_images/json-channel1.png

Accessing request elements

  • The JSON document, already parsed, is available in self.request.payload and its elements can be accessed using the dictionary notation.

    1
    2
    3
    4
    5
    6
    from zato.server.service import Service
    
    class MyService(Service):
        def handle(self):
            cust_id = self.request.payload['cust']['details']['id']
            self.logger.info('cust_id:[{}]'.format(cust_id))
    
    $ curl localhost:17010/json-example.my-service -d '{"cust": {"details": {"id":1}}}'
    
    INFO - cust_id:[1]
  • The request can be converted to a Bunch instance so it's more convenient to reference the elements.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    # Bunch
    from bunch import bunchify
    
    # Zato
    from zato.server.service import Service
    
    class MyService(Service):
        def handle(self):
            payload = bunchify(self.request.payload)
            self.logger.info('cust_id:[{}]'.format(payload.cust.details.id))
    
    $ curl localhost:17010/json-example.my-service -d '{"cust": {"details": {"id":1}}}'
    
    INFO - cust_id:[1]
  • The original JSON document, before it was parsed by Zato, is still available as self.request.raw_request.

    Note that if you want to parse it yourself you will most likely want to make sure the channel a service is available through doesn't have its data format set to JSON. Otherwise Zato would parse the request superfluously.

    1
    2
    3
    4
    5
    from zato.server.service import Service
    
    class MyService(Service):
        def handle(self):
            self.logger.info('JSON:[{}]'.format(self.request.raw_request))
    
    $ curl localhost:17010/json-example.my-service -d '{"cust": {"details": {"id":1}}}'
    
    INFO - JSON:[{"cust": {"details": {"id":1}}}]

Producing response

  • You just need to return a JSON document as a string. It doesn't matter how it's created as long as self.response.payload is assigned a JSON string. Hence all the examples below are equivalent.

    1
    2
    3
    4
    5
    from zato.server.service import Service
    
    class MyService(Service):
        def handle(self):
            self.response.payload = '{"customer_name":"Max Derkov"}'
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # stdlib
    from json import dumps
    
    # Zato
    from zato.server.service import Service
    
    class MyService(Service):
        def handle(self):
            self.response.payload = dumps({'customer_name':'Max Derkov'})
    
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    # bunch
    from bunch import Bunch
    
    # Zato
    from zato.server.service import Service
    
    class MyService(Service):
        def handle(self):
            customer = Bunch()
            customer.customer = 'Max Derkov'
            self.response.payload = customer.toJSON()
    
    $ curl localhost:17010/json-example.my-service -d ''
    {"customer_name":"Max Derkov"}
    

Simple IO (SIO)

Note

Consider using SIO if you're developing a new application or its existing data model allows you to, SIO is even more easier to work with.