move classes and methods from base.py to serialize.py
parent
37f0238fc6
commit
853bd0da21
|
@ -1,7 +1,6 @@
|
||||||
"""Base classes for type definitions in the STIX2 library."""
|
"""Base classes for type definitions in the STIX2 library."""
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import datetime as dt
|
|
||||||
import re
|
import re
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
@ -18,9 +17,10 @@ from .exceptions import (
|
||||||
)
|
)
|
||||||
from .markings import _MarkingsMixin
|
from .markings import _MarkingsMixin
|
||||||
from .markings.utils import validate
|
from .markings.utils import validate
|
||||||
from .utils import (
|
from .serialize import (
|
||||||
NOW, PREFIX_21_REGEX, find_property_index, format_datetime, get_timestamp,
|
STIXJSONEncoder, STIXJSONIncludeOptionalDefaultsEncoder, serialize,
|
||||||
)
|
)
|
||||||
|
from .utils import NOW, PREFIX_21_REGEX, get_timestamp
|
||||||
from .versioning import new_version as _new_version
|
from .versioning import new_version as _new_version
|
||||||
from .versioning import revoke as _revoke
|
from .versioning import revoke as _revoke
|
||||||
|
|
||||||
|
@ -29,88 +29,14 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from collections import Mapping
|
from collections import Mapping
|
||||||
|
|
||||||
|
# TODO: Remove STIXJSONEncoder, STIXJSONIncludeOptionalDefaultsEncoder, serialize from __all__ on next major release.
|
||||||
__all__ = ['STIXJSONEncoder', '_STIXBase', 'serialize']
|
# Kept for backwards compatibility.
|
||||||
|
__all__ = ['STIXJSONEncoder', 'STIXJSONIncludeOptionalDefaultsEncoder', '_STIXBase', 'serialize']
|
||||||
|
|
||||||
DEFAULT_ERROR = "{type} must have {property}='{expected}'."
|
DEFAULT_ERROR = "{type} must have {property}='{expected}'."
|
||||||
SCO_DET_ID_NAMESPACE = uuid.UUID("00abedb4-aa42-466c-9c01-fed23315a9b7")
|
SCO_DET_ID_NAMESPACE = uuid.UUID("00abedb4-aa42-466c-9c01-fed23315a9b7")
|
||||||
|
|
||||||
|
|
||||||
class STIXJSONEncoder(json.JSONEncoder):
|
|
||||||
"""Custom JSONEncoder subclass for serializing Python ``stix2`` objects.
|
|
||||||
|
|
||||||
If an optional property with a default value specified in the STIX 2 spec
|
|
||||||
is set to that default value, it will be left out of the serialized output.
|
|
||||||
|
|
||||||
An example of this type of property include the ``revoked`` common property.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def default(self, obj):
|
|
||||||
if isinstance(obj, (dt.date, dt.datetime)):
|
|
||||||
return format_datetime(obj)
|
|
||||||
elif isinstance(obj, _STIXBase):
|
|
||||||
tmp_obj = dict(copy.deepcopy(obj))
|
|
||||||
for prop_name in obj._defaulted_optional_properties:
|
|
||||||
del tmp_obj[prop_name]
|
|
||||||
return tmp_obj
|
|
||||||
else:
|
|
||||||
return super(STIXJSONEncoder, self).default(obj)
|
|
||||||
|
|
||||||
|
|
||||||
class STIXJSONIncludeOptionalDefaultsEncoder(json.JSONEncoder):
|
|
||||||
"""Custom JSONEncoder subclass for serializing Python ``stix2`` objects.
|
|
||||||
|
|
||||||
Differs from ``STIXJSONEncoder`` in that if an optional property with a default
|
|
||||||
value specified in the STIX 2 spec is set to that default value, it will be
|
|
||||||
included in the serialized output.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def default(self, obj):
|
|
||||||
if isinstance(obj, (dt.date, dt.datetime)):
|
|
||||||
return format_datetime(obj)
|
|
||||||
elif isinstance(obj, _STIXBase):
|
|
||||||
return dict(obj)
|
|
||||||
else:
|
|
||||||
return super(STIXJSONIncludeOptionalDefaultsEncoder, self).default(obj)
|
|
||||||
|
|
||||||
|
|
||||||
def serialize(obj, pretty=False, include_optional_defaults=False, **kwargs):
|
|
||||||
"""
|
|
||||||
Serialize a STIX object.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
obj: The STIX object to be serialized.
|
|
||||||
pretty (bool): If True, output properties following the STIX specs
|
|
||||||
formatting. This includes indentation. Refer to notes for more
|
|
||||||
details. (Default: ``False``)
|
|
||||||
include_optional_defaults (bool): Determines whether to include
|
|
||||||
optional properties set to the default value defined in the spec.
|
|
||||||
**kwargs: The arguments for a json.dumps() call.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: The serialized JSON object.
|
|
||||||
|
|
||||||
Note:
|
|
||||||
The argument ``pretty=True`` will output the STIX object following
|
|
||||||
spec order. Using this argument greatly impacts object serialization
|
|
||||||
performance. If your use case is centered across machine-to-machine
|
|
||||||
operation it is recommended to set ``pretty=False``.
|
|
||||||
|
|
||||||
When ``pretty=True`` the following key-value pairs will be added or
|
|
||||||
overridden: indent=4, separators=(",", ": "), item_sort_key=sort_by.
|
|
||||||
"""
|
|
||||||
if pretty:
|
|
||||||
def sort_by(element):
|
|
||||||
return find_property_index(obj, *element)
|
|
||||||
|
|
||||||
kwargs.update({'indent': 4, 'separators': (',', ': '), 'item_sort_key': sort_by})
|
|
||||||
|
|
||||||
if include_optional_defaults:
|
|
||||||
return json.dumps(obj, cls=STIXJSONIncludeOptionalDefaultsEncoder, **kwargs)
|
|
||||||
else:
|
|
||||||
return json.dumps(obj, cls=STIXJSONEncoder, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def get_required_properties(properties):
|
def get_required_properties(properties):
|
||||||
return (k for k, v in properties.items() if v.required)
|
return (k for k, v in properties.items() if v.required)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
"""STIX2 core serialization methods."""
|
||||||
|
|
||||||
|
import copy
|
||||||
|
import datetime as dt
|
||||||
|
|
||||||
|
import simplejson as json
|
||||||
|
|
||||||
|
from .base import _STIXBase
|
||||||
|
from .utils import find_property_index, format_datetime
|
||||||
|
|
||||||
|
|
||||||
|
class STIXJSONEncoder(json.JSONEncoder):
|
||||||
|
"""Custom JSONEncoder subclass for serializing Python ``stix2`` objects.
|
||||||
|
|
||||||
|
If an optional property with a default value specified in the STIX 2 spec
|
||||||
|
is set to that default value, it will be left out of the serialized output.
|
||||||
|
|
||||||
|
An example of this type of property include the ``revoked`` common property.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def default(self, obj):
|
||||||
|
if isinstance(obj, (dt.date, dt.datetime)):
|
||||||
|
return format_datetime(obj)
|
||||||
|
elif isinstance(obj, _STIXBase):
|
||||||
|
tmp_obj = dict(copy.deepcopy(obj))
|
||||||
|
for prop_name in obj._defaulted_optional_properties:
|
||||||
|
del tmp_obj[prop_name]
|
||||||
|
return tmp_obj
|
||||||
|
else:
|
||||||
|
return super(STIXJSONEncoder, self).default(obj)
|
||||||
|
|
||||||
|
|
||||||
|
class STIXJSONIncludeOptionalDefaultsEncoder(json.JSONEncoder):
|
||||||
|
"""Custom JSONEncoder subclass for serializing Python ``stix2`` objects.
|
||||||
|
|
||||||
|
Differs from ``STIXJSONEncoder`` in that if an optional property with a default
|
||||||
|
value specified in the STIX 2 spec is set to that default value, it will be
|
||||||
|
included in the serialized output.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def default(self, obj):
|
||||||
|
if isinstance(obj, (dt.date, dt.datetime)):
|
||||||
|
return format_datetime(obj)
|
||||||
|
elif isinstance(obj, _STIXBase):
|
||||||
|
return dict(obj)
|
||||||
|
else:
|
||||||
|
return super(STIXJSONIncludeOptionalDefaultsEncoder, self).default(obj)
|
||||||
|
|
||||||
|
|
||||||
|
def serialize(obj, pretty=False, include_optional_defaults=False, **kwargs):
|
||||||
|
"""
|
||||||
|
Serialize a STIX object.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
obj: The STIX object to be serialized.
|
||||||
|
pretty (bool): If True, output properties following the STIX specs
|
||||||
|
formatting. This includes indentation. Refer to notes for more
|
||||||
|
details. (Default: ``False``)
|
||||||
|
include_optional_defaults (bool): Determines whether to include
|
||||||
|
optional properties set to the default value defined in the spec.
|
||||||
|
**kwargs: The arguments for a json.dumps() call.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The serialized JSON object.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
The argument ``pretty=True`` will output the STIX object following
|
||||||
|
spec order. Using this argument greatly impacts object serialization
|
||||||
|
performance. If your use case is centered across machine-to-machine
|
||||||
|
operation it is recommended to set ``pretty=False``.
|
||||||
|
|
||||||
|
When ``pretty=True`` the following key-value pairs will be added or
|
||||||
|
overridden: indent=4, separators=(",", ": "), item_sort_key=sort_by.
|
||||||
|
"""
|
||||||
|
if pretty:
|
||||||
|
def sort_by(element):
|
||||||
|
return find_property_index(obj, *element)
|
||||||
|
|
||||||
|
kwargs.update({'indent': 4, 'separators': (',', ': '), 'item_sort_key': sort_by})
|
||||||
|
|
||||||
|
if include_optional_defaults:
|
||||||
|
return json.dumps(obj, cls=STIXJSONIncludeOptionalDefaultsEncoder, **kwargs)
|
||||||
|
else:
|
||||||
|
return json.dumps(obj, cls=STIXJSONEncoder, **kwargs)
|
Loading…
Reference in New Issue