SerializedData Class

Overview

The SerializedData class encapsulates serialized data with metadata about encoding and data type. It provides type-safe serialization with comprehensive support for primitive types, complex objects, and proper character encoding.

Package: keychain.core.serialized_data

from keychain.core.serialized_data import SerializedData

Class Definition

class SerializedData(SerializableObject):
    """Encapsulates serialized data with metadata about encoding and data type."""

Constructor

def __init__(
    self,
    data: Union[ctypes.c_void_p, str, int, float, bool, bytes, None] = None,
    data_type: Optional[DataType] = None,
    encoding: Optional[CharEncoding] = None,
    c_pointer: Optional[ctypes.c_void_p] = None,
) -> None

Initialize SerializedData with various data types.

Parameters:

  • data (Union[various types]) - Data to serialize, can be primitive types, bytes, or keychain objects

  • data_type (DataType, optional) - Optional data type override

  • encoding (CharEncoding, optional) - Optional encoding override

  • c_pointer (ctypes.c_void_p, optional) - Existing C pointer to wrap

Supported Data Types:

  • Primitive types: str, int, float, bool, bytes

  • Keychain objects: VerifiableData, Credential, Transaction, EncryptedData, Attestation, KeyLock

Properties

data_type()

def data_type(self) -> DataType

Get the data type of the serialized content.

Returns: The DataType enum value identifying the content type

char_encoding()

def char_encoding(self) -> CharEncoding

Get the character encoding of the serialized content.

Returns: The CharEncoding enum value for text data

serialized_content()

def serialized_content(self) -> str

Get the serialized content as a string.

Returns: The serialized data content

Data Access Methods

utf8_string()

def utf8_string(self) -> str

Get the content as a UTF-8 string.

Returns: String content (for DataType.UTF8_STRING)

Raises: ValueError if data type is not UTF8_STRING

int32()

def int32(self) -> int

Get the content as a 32-bit signed integer.

Returns: Integer value (for DataType.INT32)

Raises: ValueError if data type is not INT32

int64()

def int64(self) -> int

Get the content as a 64-bit signed integer.

Returns: Integer value (for DataType.INT64)

Raises: ValueError if data type is not INT64

boolean()

def boolean(self) -> bool

Get the content as a boolean value.

Returns: Boolean value (for DataType.BOOLEAN)

Raises: ValueError if data type is not BOOLEAN

single_float()

def single_float(self) -> float

Get the content as a single-precision float.

Returns: Float value (for DataType.SINGLE_FLOAT)

Raises: ValueError if data type is not SINGLE_FLOAT

double_float()

def double_float(self) -> float

Get the content as a double-precision float.

Returns: Float value (for DataType.DOUBLE_FLOAT)

Raises: ValueError if data type is not DOUBLE_FLOAT

verifiable_data()

def verifiable_data(self) -> "VerifiableData"

Get the content as a VerifiableData object.

Returns: VerifiableData instance (for DataType.VERIFIABLE_DATA)

Raises: ValueError if data type is not VERIFIABLE_DATA

Serialization

serialize()

def serialize(self) -> bytes

Serialize the data to bytes.

Returns: The serialized data as bytes

Usage Examples

Basic Data Types

from keychain.core.serialized_data import SerializedData
from keychain.constants import DataType, CharEncoding

# String data
text_data = SerializedData("Hello, World!")
print(f"Type: {text_data.data_type()}")  # DataType.UTF8_STRING
print(f"Content: {text_data.utf8_string()}")

# Integer data
int_data = SerializedData(42)
print(f"Type: {int_data.data_type()}")  # DataType.INT32
print(f"Value: {int_data.int32()}")

# Boolean data
bool_data = SerializedData(True)
print(f"Type: {bool_data.data_type()}")  # DataType.BOOLEAN
print(f"Value: {bool_data.boolean()}")

# Binary data
binary_data = SerializedData(b"binary content")
print(f"Type: {binary_data.data_type()}")  # DataType.BYTES

Working with Keychain Objects

# Serialize a verifiable data object
verifiable_obj = gateway.sign(persona, "Document content")
serialized_verifiable = SerializedData(verifiable_obj)

print(f"Type: {serialized_verifiable.data_type()}")  # DataType.VERIFIABLE_DATA

# Retrieve the original object
retrieved_verifiable = serialized_verifiable.verifiable_data()
assert retrieved_verifiable == verifiable_obj

Type-Safe Access

def process_serialized_data(data: SerializedData):
    """Process serialized data based on its type."""

    data_type = data.data_type()

    if data_type == DataType.UTF8_STRING:
        content = data.utf8_string()
        print(f"String content: {content}")

    elif data_type == DataType.INT32:
        value = data.int32()
        print(f"Integer value: {value}")

    elif data_type == DataType.BOOLEAN:
        flag = data.boolean()
        print(f"Boolean flag: {flag}")

    elif data_type == DataType.VERIFIABLE_DATA:
        verifiable = data.verifiable_data()
        print(f"Verifiable data: {verifiable}")

    else:
        print(f"Unsupported data type: {data_type}")

# Usage
process_serialized_data(SerializedData("test"))    # String content: test
process_serialized_data(SerializedData(123))       # Integer value: 123
process_serialized_data(SerializedData(False))     # Boolean flag: False

Serialization and Reconstruction

# Original data
original = SerializedData("Important data")

# Serialize to bytes
serialized_bytes = original.serialize()

# Reconstruct (typically done through deserialization)
# reconstructed = SerializedData.from_bytes(serialized_bytes)

# Check content preservation
print(f"Original type: {original.data_type()}")
print(f"Original content: {original.utf8_string()}")

Character Encoding Handling

# Text with specific encoding
text_data = SerializedData("Héllo, Wörld!")

print(f"Encoding: {text_data.char_encoding()}")  # CharEncoding.UTF8
print(f"Content: {text_data.utf8_string()}")

# Binary data has no character encoding
binary_data = SerializedData(b"\\x00\\x01\\x02")
print(f"Encoding: {binary_data.char_encoding()}")  # CharEncoding.BINARY

Type Safety and Validation

Data Type Checking

def safe_get_string(data: SerializedData) -> str:
    """Safely extract string content with type checking."""

    if data.data_type() != DataType.UTF8_STRING:
        raise TypeError(f"Expected UTF8_STRING, got {data.data_type()}")

    return data.utf8_string()

def safe_get_number(data: SerializedData) -> Union[int, float]:
    """Safely extract numeric content."""

    data_type = data.data_type()

    if data_type == DataType.INT32:
        return data.int32()
    elif data_type == DataType.INT64:
        return data.int64()
    elif data_type == DataType.SINGLE_FLOAT:
        return data.single_float()
    elif data_type == DataType.DOUBLE_FLOAT:
        return data.double_float()
    else:
        raise TypeError(f"Expected numeric type, got {data_type}")

Error Handling

Type Mismatch Errors

# Attempting to access data with wrong type
string_data = SerializedData("Hello")

try:
    # This will raise ValueError
    number = string_data.int32()
except ValueError as e:
    print(f"Type mismatch error: {e}")

# Correct access
text = string_data.utf8_string()  # Works correctly

See Also