### Navigation

- index
- modules |
- vSphere Automation SDK for Python 6.5.0 documentation »
- Module code »

# Source code for vmware.vapi.data.serializers.cleanjson

    """
    Serializer vAPI data values to clean (human readable/writable) json documents
    """

    __author__ = 'VMware, Inc.'
    __copyright__ = 'Copyright (c) 2015 VMware, Inc.  All rights reserved.'

    import decimal
    import logging
    import six
    import base64
    try:
        import simplejson as json
    except ImportError:
        import json

    from vmware.vapi.data.value import (
        StructValue, ErrorValue, ListValue, OptionalValue, VoidValue, StringValue,
        BooleanValue, IntegerValue, DoubleValue, BlobValue, SecretValue)
    from vmware.vapi.lib.jsonlib import canonicalize_double

    logger = logging.getLogger(__name__)

    class DataValueToJSONEncoder(json.JSONEncoder):
        """
        Custon JSON encoder that converts vAPI runtime values directly
        into JSON string representation.
        """
        # Even though __init__ is called below, pylint throws a warning
        # that base class __init__ is not called (W0231)
        def __init__(self, *args, **kwargs):  # pylint: disable=W0231
            self._dispatch_map = {
                list: self.visit_list,
                decimal.Decimal: canonicalize_double,
                StructValue: self.visit_struct_value,
                ErrorValue: self.visit_struct_value,
                ListValue: self.visit_list,
                OptionalValue: self.visit_optional_value,
                DoubleValue: self.visit_double_value,
                IntegerValue: self.visit_primitive_value,
                BooleanValue: self.visit_primitive_value,
                StringValue: self.visit_primitive_value,
                VoidValue: self.visit_primitive_value,
                BlobValue: self.visit_blob_value,
                SecretValue: self.visit_primitive_value,
            }
            json.JSONEncoder.__init__(self, *args, **kwargs)

        #
        # Even though the recommended way to subclass JSONEncoder is by overriding
        # "default", encode is being used as it will preserve the computed JSON
        # string literal for decimals. If we use default, the value returned by
        # canonicalize_double will be wrapped inside double quotes in the final
        # JSON message.
        #
        def encode(self, value):
            """
            Encode a given vAPI runtime object

            :type  value: :class:`object`
            :param value: vAPI runtime object
            :rtype: :class:`str`
            :return: JSON string
            """
            return self._dispatch_map.get(type(value), self.visit_default)(value)

        def visit_struct_value(self, value):
            """
            Visit a StructValue object

            :type  value: :class:`vmware.vapi.data.value.StructValue`
            :param value: Struct value object
            :rtype: :class:`str`
            :return: JSON string
            """
            items = {}
            for field_name, field_value in value.get_fields():
                # Omit unset optional values
                if isinstance(field_value, OptionalValue) and not field_value.is_set():
                    continue
                items[field_name] = field_value
            items = ['"%s":%s' % (k, self.encode(v))
                     for k, v in six.iteritems(items)]
            return '{%s}' % (','.join(items))

        def visit_list(self, value):
            """
            Visit a ListValue object

            :type  value: :class:`vmware.vapi.data.value.ListValue`
            :param value: List value object
            :rtype: :class:`str`
            :return: JSON string
            """
            string = ','.join([self.encode(item)
                              for item in value])
            return '[%s]' % string

        def visit_optional_value(self, value):
            """
            Visit a OptionalValue object

            :type  value: :class:`vmware.vapi.data.value.OptionalValue`
            :param value: Optional value object
            :rtype: :class:`str`
            :return: JSON string
            """
            if value.is_set():
                return '%s' % self.encode(value.value)
            else:
                return 'null'

        @staticmethod
        def visit_double_value(value):
            """
            Visit a DoubleValue object

            :type  value: :class:`vmware.vapi.data.value.DoubleValue`
            :param value: Double value object
            :rtype: :class:`str`
            :return: JSON string
            """
            return canonicalize_double(value.value)

        def visit_primitive_value(self, value):
            """
            Visit one of StringValue, IntegerValue, BooleanValue or VoidValue

            :type  value: :class:`vmware.vapi.data.value.StringValue` (or)
                :class:`vmware.vapi.data.value.IntegerValue` (or)
                :class:`vmware.vapi.data.value.BooleanValue` (or)
                :class:`vmware.vapi.data.value.VoidValue` (or)
            :param value: StringValue, IntegerValue, BooleanValue or VoidValue object
            :rtype: :class:`str`
            :return: JSON string
            """
            return json.JSONEncoder.encode(self, value.value)

        def visit_blob_value(self, value):
            """
            Visit BlobValue

            :type  value: :class:`vmware.vapi.data.value.BlobValue`
            :param value: BlobValue object
            :rtype: :class:`str`
            :return: JSON string
            """
            if six.PY3 and isinstance(value.value, str):
                # For Python3 we need to convert str to byte string for b64encode
                data_value = base64.b64encode(six.b(value.value))
            else:
                data_value = base64.b64encode(value.value)

            return json.JSONEncoder.encode(self, data_value)

        def visit_default(self, value):
            """
            This is the default visit method if the type of the input value
            does not match any type in the keys present in dispatch map.

            :type  value: :class:`object`
            :param value: Python object
            :rtype: :class:`str`
            :return: JSON string
            """
            return json.JSONEncoder.encode(self, value)

    class DataValueConverter(object):
        """
        Converter class that converts values from vAPI DataValue to clean
        JSON objects.
        """
        @staticmethod
        def convert_to_json(data_value):
            """
            Convert the given data value to a JSON string representation

            :type  data_value: :class:`vmware.vapi.data.value.DataValue`
            :param data_value: Data value to be converted
            :rtype: :class:`str`
            :return: JSON representation of the data value
            """
            return json.dumps(data_value,
                              check_circular=False,
                              separators=(',', ':'),
                              cls=DataValueToJSONEncoder)

### Navigation

- index
- modules |
- vSphere Automation SDK for Python 6.5.0 documentation »
- Module code »