JSON utilities
JSON (de)serialization framework.
The framework presented here is somewhat based on Go’s “json” package
(especially the omitempty
functionality).
- josepy.json_util.field(json_name: str, default: Optional[Any] = None, omitempty: bool = False, decoder: Optional[Callable[[Any], Any]] = None, encoder: Optional[Callable[[Any], Any]] = None) Any [source]
Convenient function to declare a
Field
with proper type annotations.This function allows to write the following code:
import josepy class JSON(josepy.JSONObjectWithFields):
typ: str = josepy.field(‘type’)
- def other_type(self) -> str:
return self.typ
- class josepy.json_util.Field(json_name: str, default: Optional[Any] = None, omitempty: bool = False, decoder: Optional[Callable[[Any], Any]] = None, encoder: Optional[Callable[[Any], Any]] = None)[source]
JSON object field.
Field
is meant to be used together withJSONObjectWithFields
.encoder
(decoder
) is a callable that accepts a single parameter, i.e. a value to be encoded (decoded), and returns the serialized (deserialized) value. In case of errors it should raiseSerializationError
(DeserializationError
).Note, that
decoder
should perform partial serialization only.- Variables
json_name (str) – Name of the field when encoded to JSON.
default – Default value (used when not present in JSON object).
omitempty (bool) – If
True
and the field value is empty, then it will not be included in the serialized JSON object, anddefault
will be used for deserialization. Otherwise, ifFalse
, field is considered as required, value will always be included in the serialized JSON objected, and it must also be present when deserializing.
- decoder(fdec: Callable[[Any], Any]) josepy.json_util.Field [source]
Descriptor to change the decoder on JSON object field.
- encoder(fenc: Callable[[Any], Any]) josepy.json_util.Field [source]
Descriptor to change the encoder on JSON object field.
- classmethod default_decoder(value: Any) Any [source]
Default decoder.
Recursively deserialize into immutable types (
josepy.util.frozendict
instead ofdict()
,tuple()
instead oflist()
).
- class josepy.json_util.JSONObjectWithFieldsMeta(name: str, bases: List[str], namespace: Dict[str, Any])[source]
Metaclass for
JSONObjectWithFields
and its subclasses.It makes sure that, for any class
cls
with__metaclass__
set toJSONObjectWithFieldsMeta
:All fields (attributes of type
Field
) in the class definition are moved to thecls._fields
dictionary, where keys are field attribute names and values are fields themselves.cls.__slots__
is extended by all field attribute names (i.e. notField.json_name
). Originalcls.__slots__
are stored incls._orig_slots
.
In a consequence, for a field attribute name
some_field
,cls.some_field
will be a slot descriptor and not an instance ofField
. For example:some_field = Field('someField', default=()) class Foo: __metaclass__ = JSONObjectWithFieldsMeta __slots__ = ('baz',) some_field = some_field assert Foo.__slots__ == ('some_field', 'baz') assert Foo._orig_slots == () assert Foo.some_field is not Field assert Foo._fields.keys() == ['some_field'] assert Foo._fields['some_field'] is some_field
As an implementation note, this metaclass inherits from
abc.ABCMeta
(and not the usualtype
) to mitigate the metaclass conflict (ImmutableMap
andJSONDeSerializable
, parents ofJSONObjectWithFields
, useabc.ABCMeta
as its metaclass).
- class josepy.json_util.JSONObjectWithFields(**kwargs: Any)[source]
JSON object with fields.
Example:
class Foo(JSONObjectWithFields): bar = Field('Bar') empty = Field('Empty', omitempty=True) @bar.encoder def bar(value): return value + 'bar' @bar.decoder def bar(value): if not value.endswith('bar'): raise errors.DeserializationError('No bar suffix!') return value[:-3] assert Foo(bar='baz').to_partial_json() == {'Bar': 'bazbar'} assert Foo.from_json({'Bar': 'bazbar'}) == Foo(bar='baz') assert (Foo.from_json({'Bar': 'bazbar', 'Empty': '!'}) == Foo(bar='baz', empty='!')) assert Foo(bar='baz').bar == 'baz'
- encode(name: str) Any [source]
Encode a single field.
- Parameters
name (str) – Name of the field to be encoded.
- Raises
errors.SerializationError – if field cannot be serialized
errors.Error – if field could not be found
- to_partial_json() Dict[str, Any] [source]
Partially serialize.
Following the example, partial serialization means the following:
assert isinstance(Bar().to_partial_json()[0], Foo) assert isinstance(Bar().to_partial_json()[1], Foo) # in particular... assert Bar().to_partial_json() != ['foo', 'foo']
- Raises
josepy.errors.SerializationError – in case of any serialization error.
- Returns
Partially serializable object.
- josepy.json_util.encode_b64jose(data: bytes) str [source]
Encode JOSE Base-64 field.
- Parameters
data (bytes) –
- Return type
str
- josepy.json_util.decode_b64jose(data: str, size: Optional[int] = None, minimum: bool = False) bytes [source]
Decode JOSE Base-64 field.
- Parameters
data (unicode) –
size (int) – Required length (after decoding).
minimum (bool) – If
True
, thensize
will be treated as minimum required length, as opposed to exact equality.
- Return type
bytes
- josepy.json_util.encode_hex16(value: bytes) str [source]
Hexlify.
- Parameters
value (bytes) –
- Return type
unicode
- josepy.json_util.decode_hex16(value: str, size: Optional[int] = None, minimum: bool = False) bytes [source]
Decode hexlified field.
- Parameters
value (unicode) –
size (int) – Required length (after decoding).
minimum (bool) – If
True
, thensize
will be treated as minimum required length, as opposed to exact equality.
- Return type
bytes
- josepy.json_util.encode_cert(cert: josepy.util.ComparableX509) str [source]
Encode certificate as JOSE Base-64 DER.
- Return type
unicode
- josepy.json_util.decode_cert(b64der: str) josepy.util.ComparableX509 [source]
Decode JOSE Base-64 DER-encoded certificate.
- Parameters
b64der (unicode) –
- Return type
OpenSSL.crypto.X509
wrapped inComparableX509
- josepy.json_util.encode_csr(csr: josepy.util.ComparableX509) str [source]
Encode CSR as JOSE Base-64 DER.
- Return type
unicode
- josepy.json_util.decode_csr(b64der: str) josepy.util.ComparableX509 [source]
Decode JOSE Base-64 DER-encoded CSR.
- Parameters
b64der (unicode) –
- Return type
OpenSSL.crypto.X509Req
wrapped inComparableX509
- class josepy.json_util.TypedJSONObjectWithFields(**kwargs: Any)[source]
JSON object with type.
- typ: str = NotImplemented
Type of the object. Subclasses must override.
- type_field_name: str = 'type'
Field name used to distinguish different object types.
Subclasses will probably have to override this.
- TYPES: Dict[str, Type] = NotImplemented
Types registered for JSON deserialization
- classmethod register(type_cls: Type[josepy.json_util.TypedJSONObjectWithFields], typ: Optional[str] = None) Type[josepy.json_util.TypedJSONObjectWithFields] [source]
Register class for JSON deserialization.
- classmethod get_type_cls(jobj: Mapping[str, Any]) Type[josepy.json_util.TypedJSONObjectWithFields] [source]
Get the registered class for
jobj
.
- to_partial_json() Dict[str, Any] [source]
Get JSON serializable object.
- Returns
Serializable JSON object representing ACME typed object.
validate()
will almost certainly not work, due to reasons explained injosepy.interfaces.IJSONSerializable
.- Return type
dict
- classmethod from_json(jobj: Mapping[str, Any]) josepy.json_util.TypedJSONObjectWithFields [source]
Deserialize ACME object from valid JSON object.
- Raises
josepy.errors.UnrecognizedTypeError – if type of the ACME object has not been registered.